[
  {
    "path": ".gitignore",
    "content": ".settings\n.project\n.svn\n.idea/"
  },
  {
    "path": "CHANGELOG",
    "content": "0.5.2   (2019-01-30)\n--------------------\n- 功能新增\n  * util/ajax/dwr 在请求异常时控制台输出请求信息\n- BUG修复模块\n  * 修正低版本跨域代理文件发送请求时先序列化对象\n  * 修正 util/cache/list 模块隐式声明导致的全局变量污染\n\n0.5.1   (2018-10-11)\n--------------------------------------------------------\n- BUG修复模块\n  * 修正 util/ajax/rest 无法发送 null 数据的问题\n  * 修正 util/animation/animation 在 safari12 中当前时间异常 bug\n\n0.5.0   (2018-06-22)\n--------------------------------------------------------\n- BUG修复模块\n  * 修正 util/cache/list 模块 GC 异常\n  * 修正 util/template/trimpath 重复引入异常\n\n0.4.9   (2018-04-12)\n--------------------------------------------------------\n- 功能支持\n  * 支持 res 依赖插件注入地址\n\n0.4.7   (2018-04-12)\n--------------------------------------------------------\n- BUG修复模块\n  * base/util 模块的 _$absolute 接口支持相对协议\n  * util/timer/animation 的 requestAnimationFrame 接口返回标识\n\n0.4.6   (2017-11-09)\n--------------------------------------------------------\n- BUG修复模块\n  * base/util 模块的 _$url2origin 接口支持相对协议\n  * util/ajax/loader/text 修正 XHR 重复加载文本内容时被缓存问题\n\n0.4.5   (2017-09-14)\n--------------------------------------------------------\n- 功能支持\n  * util/ajax/tag 模块增加 _$loadTemplate 接口需要跨域载入的时候采用 ajax 先加载文本再解析内容\n\n- 功能变化\n  * util/ajax/tag 模块 _$loadHtml 接口回退不支持跨域载入\n\n0.4.4   (2017-09-12)\n--------------------------------------------------------\n- 功能支持\n  * util/dispatcher/dispatcher 增加根据别名取模块 UMI 接口 _$getUMIByAlias\n  * util/cursor/cursor 增加 _$lineno 支持获取当前光标所在的行\n  * util/template/tpl _$parseTemplate 支持 type 为 nej/* 的 script 标签解析\n\n- 功能变化\n  * util/cache/list _$addItem 接口支持批量添加列表项\n  * util/ajax/tag 模块 _$loadHtml 接口需要跨域载入的时候采用 ajax 先加载文本再解析内容\n  * NEJ.define 处理过程忽略 NEJ 模板封装脚本，即 type=\"nej/*\" 的 script 标签\n\n0.4.3   (2017-06-26)\n--------------------------------------------------------\n- 功能支持\n  * 添加消息总线机制\n\n0.4.2   (2017-06-05)\n--------------------------------------------------------\n- 功能变化\n  * util/ajax/rest 支持从输入的data中解析地址上的rest变量\n  * util/ajax/rest 支持 :PARAM 的地址变量格式\n  * util/cache/abstract 支持在 __doSendRequest 的hook接口中传入当前请求key\n  * base/element getChildren接口兼容IOS8的XML DOM\n\n\n0.4.1   (2017-06-01)\n--------------------------------------------------------\n- 功能变化\n  * bower 安装时忽略 test,doc,res,demo 目录\n\n0.4.0   (2017-04-10)\n--------------------------------------------------------\n- 功能支持\n  * 列表删除cache中回传服务器返回的结果\n\n- BUG修复模块\n  * util/flash/flash 删除flash检测次数限制\n\n0.3.9   (2017-03-22)\n--------------------------------------------------------\n- BUG修复模块\n  * 修复相对协议模块载入地址错误 (支持https)\n  * 修复platform模块无法判断Google Chrome for IOS\n  * 修复列表取单项详情时候传入的主键名称为 id\n\n0.3.8   (2017-02-09)\n--------------------------------------------------------\n- 功能支持\n  * 剪切板支持跨域flash引入\n  * NEJ 模块文件载入支持文件名版本号\n\n- BUG修复模块\n  * 修复 regularModule build 参数输入\n\n\n0.3.7   (2017-01-09)\n--------------------------------------------------------\n- 功能支持\n  * 支持缓存列表填充验证时重写列表项验证逻辑\n  * 支持缓存在 filter 阶段直接返回结果阻止发送请求\n  * 增加 __getListReqKey/__getItemReqKey 取请求标识\n  * 支持 __doSendRequest 时使用 options 配置请求地址\n  * __doSendRequest 过程的事件支持输入 cnf 配置信息对象\n\n- BUG修复模块\n  * 修正 util/cache/list 下 getList/getItem 的 ext 参数回传异常\n\n\n0.3.5   (2016-11-22)\n--------------------------------------------------------\n- BUG修复模块\n  * 修正 IE8 下取 DOM 属性异常问题\n\n\n0.3.4   (2016-11-16)\n--------------------------------------------------------\n- 功能支持\n  * 支持缓存配置 type 属性\n\n0.3.3   (2016-10-31)\n--------------------------------------------------------\n- 功能支持\n  * 缓存基类支持 _$dump 静态接口\n  * 支持 JSONP 接口调用\n\n- BUG修复模块\n  * cache 基类 __doSendRequest 接口判空逻辑调整\n  * XDR 请求时针对字符串数据序列化的问题\n\n0.3.2   (2016-10-12)\n--------------------------------------------------------\n- NEJ.define 注入增加 css 插件支持\n\n0.3.1   (2016-08-27)\n--------------------------------------------------------\n- BUG修复模块\n  * util/dispatcher/module 修复 regularModule init 参数\n  * 删除文档中单页模块的 template 打包标记\n\n0.3.0   (2016-07-18)\n--------------------------------------------------------\n- BUG修复模块\n  * base/klass 清除无效条件判断\n  * base/util string2object/object2string接口处理不合法URL异常\n  * util/cache/list 清除请求队列异常\n  * util/module/list 瀑布流列表分页问题\n  * define.js 在head中引入的异常\n\n- 功能支持\n  * util/dispatcher/dispatcher 重定向时模块退出判断支持\n  * util/dispatcher/module 模块构建时支持UMI配置参数\n\n0.2.8   (2016-03-29)\n0.2.7\n--------------------------------------------------------\n- 增加regularjs模块的支持\n  * util/dispatcher/regularModule.js\n- 功能增加\n  * base/element 增加 _$getParent 接口\n  * util/list/module 增加 _$nextPage,_$prevPage,_$pageTo 接口\n\n0.2.6   (2015-09-07)\n0.2.5\n--------------------------------------------------------\n- 兼容处理\n  * define.js识别nej内敛函数判断条件调整，支持 NEJ.define和define函数\n  * util/cache/cache兼容到nej.ut._$$Cache类名\n  * util/dispatcher/module兼容到nej.ut._$$Module类名\n  * 删除XDR请求回调中的try/catch，由应用逻辑自己保证批量请求的异常处理\n  * util/sortable/sortable在mousemove事件中开始拖拽\n\n0.2.4   (2015-01-20)\n--------------------------------------------------------\n- bug修正\n  * 修正模块调度器在带flash的ie下标题出现hash串的问题\n  * 修正在define.js之后内联非NEJ脚本的依赖异常\n\n0.2.3\n--------------------------------------------------------\n- bug修正\n  * 修正IE9下placeholder异常\n  * 修正IE6下弹层无法盖住select问题\n  * 修正日历在跨年选择时年份错误问题\n- 功能支持\n  * webform支持多选select\n\n0.2.2   (2014-11-18)\n--------------------------------------------------------\n- bug修正\n  * base/util._$encode\n- tag for 20141118\n\n0.2.1   (2014-11-13)\n--------------------------------------------------------\n- 增加API/控件支持\n  * ui/lightbox/lightbox\n  * util/lightbox/lightbox\n- webform组件对date类型的表单元素增加data-time支持\n\n0.2.0   (2014-11-05)\n--------------------------------------------------------\n- 修正define对实例返回结果的注入\n- 增加json!类型的插件注入\n- 增加regularjs!类型的插件注入\n- 增加API/控件支持\n  * util/selector/cascade\n  * util/suggest/at\n  * util/sort/*\n  * util/es/array\n  * util/lazy/*\n  * util/scroll/smart\n\n0.1.0   (2014-09-01)\n--------------------------------------------------------\n- 重构类模型，__super作为所有接口调用父类同名接口的方式\n- 独立类模型实现文件至{lib}base/klass.js\n- 支持AMD形式的路径，如base/klass，pro/extend/api\n- 支持纯文本资源的依赖载入\n- 增加依赖注入，保留兼容模式下名字空间形式\n- 独立平台适配，删除patched目录，独立到各API、控件\n- 清理没用控件或者后期重新开发控件及API\n  * 删除native\n  * 删除util/xmpp\n  * 删除util/gesture\n  * 删除util/ajax/connect.js\n  * 删除util/cache/config.js\n  * 删除util/dispatch/v1\n  * 删除util/module\n  * 删除util/tb.resizer\n  * 删除util/oauth\n  * 删除util/sorter\n  * 删除ui/arrows\n  * 删除ui/loading\n  * 删除ui/loadmore\n  * 删除ui/pullrefresh\n  * 删除ui/sorter\n  * util/cache/storage.manager.js 更名为 util/cache/manager.js\n\ndefine.js\n- NEJ.config接口名称改为NEJ.deps\n- 删除define.cmp.js兼容支持\n\nbase/util.js\n- 删除_$mergeList\n- 迁移_$dom2object、_$xml2object至{lib}base/element.js\n- 增加接口_$query、_$merge、_$fetch替代原NEJ.Q、NEJ.X、NEJ.EX\n\nbase/element.js\n- 交换_$getMaxBox接口输入参数顺序\n- 修改_$dom2object第二个参数为非必传参数\n- 独立_$highlight接口至util/highlight/highlight\n- 独立_$hover接口至util/hover/hover\n- 独立_$focus接口至util/focus/focus\n- 独立_$toggle接口至util/toggle/toggle\n- 独立_$cursor接口至util/cursor/cursor\n\nbase/platform.js\n- 删除_$NOT_PATCH\n- 增加_$support/_$is接口\n\nbase/event.js\n- 删除接口_$stopClick\n\nutil/event.js\n- 更改_$$Event类名为_$$EventTarget，兼容_$$Event\n- _$addEvent接口功能使用_$pushEvent代替原来的_$setEvent\n- 删除_$api接口\n\nutil/ajax/dwr.js\n- 删除_$setProxy接口\n\nutil/ajax/tag.js\n- 修改onloaded载入回调函数名称为onload\n\nutil/cache/storage.js\n- 删除_$cloneDataInStorage接口\n\nutil/dispatcher\n- 合并module.2.js和module.base.js\nutil/dispatcher.2.js\n- 删除_$apply接口，使用_$redirect代替\n\nutil/page/page.js\n- 删除_e._$page接口\n\nutil/template/tpl.js\n- 删除_e._$setup接口\n\nutil/template/jst.js\n- 修改接口名称\n  _$addHtmlTemplate     -> _$add\n  _$getHtmlTemplate     -> _$get\n  _$getHtmlTemplateSeed -> _$seed\n  _$renderHtmlTemplate  -> _$render\n  _$registJSTExt        -> _$extend\n\nutil/tab/tab.js\n- onchange事件阻止属性nostop改为stopped\n- 删除nej.e._$tab接口\n\nutil/cache/share.js\n- localCache._$addEvent代替原nej.v._$addEvent方式添加事件监听\n\n\n\n\n\n"
  },
  {
    "path": "LICENSE",
    "content": "NEJ is released under the MIT license\n\nCopyright 2012 (c) NetEase, Inc\n\nUses \nTrimPath  (http://code.google.com/p/trimpath/)\njson2.js  (http://www.JSON.org/json2.js)\njson_parse.js (https://github.com/douglascrockford/JSON-js)\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# NEJ - JavaScript Framework\n\n## 概述 \n\n跨平台WEB前端开发框架，主要提供Web端SDK用于开发Web应用，服务器端SDK用于整合解决方案的服务器端实现\n\n主要特性包括：\n\n* [依赖管理系统](./doc/DEPENDENCY.md)支持 \n* [平台适配系统](./doc/PLATFORM.md)支持（浏览器、移动APP、桌面APP等）\n* 丰富可灵活扩展的[控件系统](./doc/WIDGET.md)（可验证表单、列表、拖拽、滑块、日历、富文本编辑器等）\n* 多方案集成（[模板系统](./doc/TEMPLATE.md)、[可组合的模块化开发](./doc/DISPATCHER.md)、[单页系统按需载入](./doc/DISPATCHER.md)、[基于配置的跨域异步请求](./doc/AJAX.md)等）\n* 可自由定制的产品发布（按平台定制、按功能定制）\n* 工具支持（[NEJ工具集](https://github.com/genify/toolkit2)、[NEI工具集](https://github.com/genify/nei)等）\n* 新技术整合（对于高端目标平台自动应用新技术）\n\n## 使用 \n\n[API手册](http://nej.netease.com/help/index.html)\n\n页面引入define.js，可以下载到本地也可以使用NEJ服务器上的define.js（ http://nej.netease.com/nej2/src/define.js ），通过切换define.js的路径切换使用的NEJ库\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <title>use nej</title>\n    <meta charset=\"utf-8\"/>\n  </head>\n  <body>\n    <textarea id=\"txt-0\"></textarea>\n    <input type=\"text\" id=\"input-id-0\" maxlength=\"100\"/>\n    \n    <script src=\"/path/to/nej/define.js\"></script>\n    <script>\n      NEJ.define([\n        'util/counter/counter'\n      ],function(_e){\n          _e._$counter('txt-0');\n          _e._$counter('input-id-0');\n          \n          // TODO\n      });\n    </script>\n    <script>\n      // 习惯链式的同学也可以这样使用\n      NEJ.define([\n        'util/chain/chainable',\n        'util/counter/counter'\n      ],function($){\n          $('#txt-0')._$counter();\n          $('#input-id-0')._$counter();\n          \n          // TODO\n      });\n    </script>\n  </body>\n</html>\n```\n\n## 文档\n\n* 依赖管理 [文档](./doc/DEPENDENCY.md)\n* 平台适配 [文档](./doc/PLATFORM.md)\n* 窗体消息 [文档](./doc/MESSAGE.md)\n* 远程调用 [文档](./doc/AJAX.md)\n* 模块调度 [文档](./doc/DISPATCHER.md)\n* 模板系统 [文档](./doc/TEMPLATE.md)\n* 组件系统 [文档](./doc/WIDGET.md)"
  },
  {
    "path": "bower.json",
    "content": "{\n    \"name\": \"nej\",\n    \"version\": \"0.5.2\",\n    \"homepage\": \"https://github.com/genify/nej\",\n    \"authors\": [\n        \"genify <caijf@corp.netease.com>\"\n    ],\n    \"description\": \"JavaScript Cross-Platform Framework\",\n    \"main\": \"./src/define.js\",\n    \"keywords\": [\n        \"nej\",\n        \"javascript\",\n        \"cross platform\",\n        \"framework\"\n    ],\n    \"ignore\": [\n        \".*\",\n        \"**/test/\",\n        \"**/demo/\",\n        \"doc\",\n        \"res\"\n    ],\n    \"license\": \"MIT\"\n}"
  },
  {
    "path": "doc/AJAX.md",
    "content": "# 前后端通讯系统\n\n## 概述\n\n随着富媒体应用的不断发展成熟，AJAX的应用得到越来越多的普及，而AJAX应用的一个核心功能-异步数据载入功能也就显得越为重要，包括HTML5的发展也为此提供了强大的支持。\n\n对于富媒体WEB应用来说异步请求为其必不可缺的组成部分，对于同域的异步请求基本无需做太多额外配置，对于跨域的请求W3C也提供了相应的规范的支持，但是由于各浏览器对规范支持的程度的差异导致最终使用时会有一些差别，而NEJ框架针对这些差异及低版本的跨域支持做了封装，对上层应用而言可以使用统一的API做同域或非同域的异步请求。\n\n## 代理模式\n\nNEJ中主要通过客户端中间代理的方式实现异步请求，根据代理实现方式的差别主要提供以下几种模式的支持，具体应用可以根据实际情况选择使用的代理模式\n\n* W3C的Cross-Origin Resource Sharing规范，后面简称CORS规范\n* Frame代理\n* Flash代理\n* 文件上传代理\n\nNEJ在所有平台均提供了以上三种模式的支持，由于各模式均有自己的一些缺陷，因此实际应用时请按照具体情况选择不同的模式\n\n\n## CORS规范\n\nCORS规范详细描述见W3C的《[Cross-Origin Resource Sharing](http://www.w3.org/TR/cors/)》部分\n\n### 原理\n\n#### 术语\n\n##### simple method\n\n请求方式为以下几种之一，区分大小写\n\n* GET\n* HEAD\n* POST\n\n##### simple header\n\n请求头信息只包含以下几种，不区分大小写\n\n* Accept\n* Accept-Language\n* Content-Language\n\n或者\n\n* Content-Type\n\n但是其值只能为以下几种之一，不区分大小写\n\n* application/x-www-form-urlencoded\n* multipart/form-data\n* text/plain\n\n##### simple response header\n\n返回头信息包含以下几种，不区分大小写\n\n* Cache-Control\n* Content-Language\n* Content-Type\n* Expires\n* Last-Modified\n* Pragma\n\n##### user credentials\n\n指定安全相关信息传输方式，包括\n\n* cookies\n* HTTP authentication\n* client-side SSL certificates\n\n#### 控制字段\n\n各字段构建阶段相见[流程](#流程)部分\n\n##### 请求相关\n\n* [Origin](http://www.w3.org/TR/cors/#origin-request-header)\n* [Access-Control-Request-Method](http://www.w3.org/TR/cors/#access-control-request-method-request-header)\n* [Access-Control-Request-Headers](http://www.w3.org/TR/cors/#access-control-request-headers-request-header)\n\n##### 返回相关\n\n* [Access-Control-Allow-Origin](http://www.w3.org/TR/cors/#access-control-allow-origin-response-header)\n* [Access-Control-Allow-Methods](http://www.w3.org/TR/cors/#access-control-allow-methods-response-header)\n* [Access-Control-Allow-Headers](http://www.w3.org/TR/cors/#access-control-allow-headers-response-header)\n* [Access-Control-Allow-Credentials](http://www.w3.org/TR/cors/#access-control-allow-credentials-response-header)\n* [Access-Control-Max-Age](http://www.w3.org/TR/cors/#access-control-max-age-response-header)\n* [Access-Control-Expose-Headers](http://www.w3.org/TR/cors/#access-control-expose-headers-response-header)\n\n#### 流程\n\n##### 流程概况\n\n![CORS请求](http://img0.ph.126.net/R6pynYIBRt0rv2CJvzjhhA==/6608753177213290299.png)\n\n1.  浏览器捕获到a.b.com应用往x.y.com的服务器发起的请求\n2.  浏览器检查请求情况确定是否需要先做一次预请求来验证x.y.com的服务器是否允许发当前请求过去，如果需要发预请求则浏览器发起一个OPTIONS的请求到x.y.com的服务器验证继续第3步，否则直接发送请求到x.y.com服务器继续第5步\n3.  服务器根据浏览器发过来的header信息，然后根据服务器端对资源的配置返回资源的实际控制权限配置\n4.  浏览器验证预请求返回的信息，判断是否可以将请求发送到x.y.com的服务器，如果不行则异常退出，否则继续第5步\n5.  浏览器发送实际请求至x.y.com服务器\n6.  服务器返回请求数据及资源控制配置信息至浏览器\n7.  浏览器验证资源控制信息是否允许当前实际请求的取到数据，如果不允许则异常退出，否则继续第8步\n8.  浏览器返回x.y.com返回的数据至a.b.com的应用\n\n##### User Agent相关流程\n\n###### check preflight request\n\n![check preflight request](http://img2.ph.126.net/r-8_Drfm2tKxTGZEDK8_3Q==/2987012452953704123.png)\n\n在没有预请求缓存的情况下，是否发送预请求主要取决于以下两个条件\n\n* 请求方式是否[simple method](#simple method)\n* 没有自定义头信息，或者自定义头信息符合[simple header](#simple header)\n\n###### make preflight request\n\n![make preflight request](http://img0.ph.126.net/9_h6lb6N37bvStq5Ze2MFw==/6619176547444246158.png)\n\n这里主要完成以下信息的设置\n\n* [Origin](http://www.w3.org/TR/cors/#origin-request-header)\n* [Access-Control-Request-Method](http://www.w3.org/TR/cors/#access-control-request-method-request-header)\n* [Access-Control-Request-Headers](http://www.w3.org/TR/cors/#access-control-request-headers-request-header)\n\n###### cache preflight request\n\n![cache preflight request](http://img2.ph.126.net/qxQ_SDJ1oBbWdjgea0r4bw==/4806466702411514477.png)\n\n###### check preflight response\n\n![check preflight response](http://img1.ph.126.net/5tqXaNkLoUQ_ny5yhWpX5w==/1612570141676339530.png)\n\n这里需要注意：如果设置了[user credentials](#user credentials)，则返回的Access-Control-Allow-Origin必须与请求的Origin完全一致，包括大小写\n\n##### Server相关流程\n\n###### response preflight request\n\n![response preflight request](http://img0.ph.126.net/STUHWTmsoH_h9V49H9BL-Q==/3301420001939732538.png)\n\n这里主要完成以下信息的设置\n\n* [Access-Control-Allow-Origin](http://www.w3.org/TR/cors/#access-control-allow-origin-response-header)\n* [Access-Control-Allow-Credentials](http://www.w3.org/TR/cors/#access-control-allow-credentials-response-header)\n* [Access-Control-Max-Age](http://www.w3.org/TR/cors/#access-control-max-age-response-header)\n* [Access-Control-Allow-Methods](http://www.w3.org/TR/cors/#access-control-allow-methods-response-header)\n* [Access-Control-Allow-Headers](http://www.w3.org/TR/cors/#access-control-allow-headers-response-header)\n\n###### response actual request\n\n![response actual request](http://img2.ph.126.net/3ho2hdTzTKERNY6BTXda5g==/6619581167723268848.png)\n\n这里除了返回[response preflight request](#response preflight request)阶段返回的头信息外，还可以返回Access-Control-Expose-Headers用来控制客户端脚本中可获取的返回头信息\n\n* [Access-Control-Expose-Headers](http://www.w3.org/TR/cors/#access-control-expose-headers-response-header)\n\n### 缺陷\n\n需要高版本浏览器支持，Trident引擎的浏览器需要IE10以上才支持\n\n## Frame代理\n\n此模式主要参照CORS规范原理，通过在目标服务器放置一个代理文件，然后通过该代理文件来与服务器端进行数据交互，返回数据通过消息通讯返回给上层应用来实现跨域的数据交互。\n\n此方式也支持通过代理文件配置资源可访问的来源\n\n### 原理\n\n![Frame代理跨域流程](http://img2.ph.126.net/cPIDakXJZLhpnldZrZpZ7g==/6608721291376084913.png)\n\n1.  当a.b.com的应用要往x.y.com的服务器取数据时，首先会用iframe载入预先放置在x.y.com服务器上的代理文件\n2.  服务器端返回做了配置的代理文件\n3.  代理文件载入完成后a.b.com的应用将要发送的请求指令通过消息通信方式传递给代理文件\n4.  代理文件验证a.b.com是否在预先配置的白名单中，如果不在则异常返回，否则直接发送请求至x.y.com服务器\n5.  服务器返回数据至代理文件\n6.  代理文件通过消息通讯机制将请求结果返回给a.b.com的应用\n\n### 缺陷\n\n该模式主要有以下几个问题：\n\n* 需要在目标服务器放置代理文件\n* 由于首次发起请求时需要载入代理文件，在载入代理文件之前的所有请求都会存在一定的延时\n* 对于低版本浏览器受限于消息通讯机制的限制，对于并发量大的请求返回时可能存在较大延时\n\n## Flash代理\n\n此模式与Frame代理模式类似，主要差别在于请求通过Flash来发送，因此可以利用Flash的策略文件crossdomain.xml来控制资源的共享权限\n\n### 原理\n\n![Flash代理跨域流程](http://img1.ph.126.net/HVFJFekgjG23O_z-Fq2yLA==/6608433219329605678.png)\n\n1.  a.b.com的应用从自己的服务器上载入用来做请求的flash代理文件\n2.  a.b.com服务器返回代理flash文件\n3.  flash准备完毕后a.b.com应用将请求指令发送给flash\n4.  flash从目标服务器x.y.com载入策略文件crossdomain.xml\n5.  flash验证策略文件是否允许a.b.com访问x.y.com的资源，如果不允许则异常返回，否则发送请求至目标服务器\n6.  x.y.com服务器返回数据至flash代理中\n7.  flash代理将请求返回的数据提交到a.b.com的应用中\n\n### 缺陷\n\n该模式主要有以下几个问题：\n\n* 需要浏览器支持flash\n* 需要在目标服务器配置flash策略文件crossdomain.xml\n* 由于首次发起请求时需要载入flash代理文件，在载入代理文件之前的所有请求都会存在一定的延时\n\n## 文件上传\n\n对于无刷新的系统来说，如果需要上传文件则必须也需要不刷新当前页面，对于高版本浏览器使用W3C中定义的XMLHttpRequest规范来实现，低版本则采用Frame代理的方式来实现\n\n### 原理\n\n#### XMLHttpRequest\n\n对于高版本浏览器使用W3C规范中对XMLHttpRequest的定义来实现，相关接口定义\n\n![uploader in XMLHttpRequest](http://img2.ph.126.net/prhGaXl0rn9g7CY3BK1p9A==/6599280884541303788.png)\n\nXMLHttpRequest关于上传相关的数据发送流程\n\n![send in XMLHttpRequest](http://img0.ph.126.net/KMsO751gC-M32-m3e6Qxlw==/6608621235817958265.png)\n\n上传这里主要会采用Blob或FormData数据形式发送到服务器\n\n#### Form+Frame代理\n\n对于无法支持XMLHttpRequest直接进行文件上传的浏览器，采用Form表单+Frame代理的方式来实现\n\n![form+frame upload](http://img1.ph.126.net/TLJiqwe6DY31CZIddXXYTQ==/6619487709234907039.png)\n\n1.  a.b.com应用中包含要上传的文件的Form表单POST至目标服务器x.y.com，如果需要轮询进度的话此时开始起定时器轮询上传进度\n2.  x.y.com将返回结果按照nej\\_proxy\\_upload.html模板文件给定的格式返回结果至Frame代理中\n3.  Frame代理通过消息通讯机制将上传结果返回到a.b.com的应用中\n\n### 缺陷\n\n低版本返回的数据格式同高版本的不一致，因此服务器端需额外判断当前请求类别，然后根据类别返回数据内容\n\n## NEJ封装\n\nNEJ作为跨平台的WEB前端开发框架在跨域前后端通讯方面根据以上原理做了较好的封装，上层应用只需使用相应API即可\n\n### 配置\n\n#### 高版本CORS配置\n\n##### 添加依赖\n\n如果是maven工程，在pom.xml文件中加入依赖即可\n\n```xml\n<dependency>\n    <groupId>com.netease.wd</groupId>\n    <artifactId>cross-origin</artifactId>\n    <version>0.0.2</version>\n</dependency>\n```\n\n如果是非maven工程，将jar包加入到工程的classpath中即可，[下载jar包](http://mvn.hz.netease.com/artifactory/webapp/browserepo.html?pathId=libs-releases%3Acom%2Fnetease%2Fwd%2Fcross-origin%2F0.0.2%2Fcross-origin-0.0.2.jar)\n\n##### 配置web.xml\n\n在web.xml文件中引入cross-origin filter的配置，并添加需要的初始化参数\n\n```xml\n<filter>\n    <filter-name>cross-origin</filter-name>\n    <filter-class>com.netease.wd.crossorigin.filter.CrossOriginFilter</filter-class>\n</filter>\n```\n\n配置参数说明\n\n| 参数名称 | 参数说明 |\n| :---     | :---     |\n| allowOrigins | 允许访问资源的origin列表。必须是完整的域名，包含scheme, host和port(如果有的话),以,分隔，且区分大小写。 如：http://a.b.com, http://a.b.com:8080。作用于preflight请求以及后面的正式访问请求。访问的请求必须带有Origin header，并且内容要完全匹配列表中的某个值才允许访问后面的资源。如果对origin无限制，则该项可以配置成*。|\n| allowMethods | 允许访问资源的method列表，以,分隔，区分大小写。如：GET, POST等。在preflight请求中，必须带有“Access-Control-Request-Method” header，并且值必须与列表中的某个值匹配，才能允许访问后续资源。如果对Method无限制，可以将该项配置成*。 |\n| allowHeaders | 访问资源的请求所允许携带的header列表。Filter会检查与preflight请求的“Access-Control-Request-Headers” header，获取请求访问的header列表。Header列表所包含的header必须全部出现在allowHeaders列表中（不区分大小写），才允许访问后续资源。如果对header无限制，可将该项配置为*。 |\n| supportCredentials | 是否支持credentials选项，可选值为：true或者false。如果为true，则在响应中加入“Access-Control-Allow-Credentials”为true的header。 |\n| maxAge | 指定preflight request缓存的时间长度，单位为秒。配置后，会在响应中加入相应的“Access-Control-Max-Age” header和秒数。 |\n| exposeHeaders | 允许expose的header列表，以,分隔。配置该项后，在正式访问请求的响应中会带上“Access-Control-Expose-Header” header。 |\n| checkReferer | 是否检查referer header，可选值：true或false。该选项主要用于处理IE某些版本下，不支持CORS并且跨域请求不带Origin header的情况。打开该开关后，如果请求没有Origin header，则会比较Referer和Host来判断请求是否存在跨域。如果有跨域，则从Referer中提取出Origin域名，之后的流程则与前面描述的流程一致。 |\n\n##### 配置url mapping\n\n将需要做CORS处理的资源与filter进行关联即可\n\n```xml\n<filter-mapping>\n    <filter-name>cross-origin</filter-name>\n    <url-pattern>/path/to/resources</url-pattern>\n</filter-mapping>\n```\n\n##### 使用范例\n\n```xml\n<filter>\n    <filter-name>cross-origin</filter-name>\n    <filter-class>com.netease.wd.crossorigin.filter.CrossOriginFilter</filter-class>\n    <init-param>\n        <param-name>allowOrigins</param-name>\n        <param-value>http://a.b.com, http://a.b.com:8080</param-value>\n    </init-param>\n    <init-param>\n        <param-name>allowMethods</param-name>\n        <param-value>GET, POST, OPTIONS</param-value>\n    </init-param>\n    <init-param>\n        <param-name>allowHeaders</param-name>\n        <param-value>*</param-value>\n    </init-param>\n    <init-param>\n        <param-name>supportCredentials</param-name>\n        <param-value>true</param-value>\n    </init-param>\n    <init-param>\n        <param-name>maxAge</param-name>\n        <param-value>60</param-value>\n    </init-param>\n    <init-param>\n        <param-name>exposeHeaders</param-name>\n        <param-value>Set-Cookie, Max-Age</param-value>\n    </init-param>\n    <init-param>\n        <param-name>checkReferer</param-name>\n        <param-value>true</param-value>\n    </init-param>\n</filter>\n<filter-mapping>\n    <filter-name>cross-origin</filter-name>\n    <url-pattern>/path/to/resources</url-pattern>\n</filter-mapping>\n```\n\n##### 上传返回结果兼容\n\n在上面文件上传部分我们分析发现对于使用不同的上传策略，API需根据策略返回不同的结果，为了减少此方式对应用层的影响，在jar包中提供了统一的方法供使用，主要封装了\n\n* 对于支持CORS的浏览器，服务器只需要返回json字符串\n* 对于不支持CORS的浏览器，服务器需要返回特定格式的html页面内容\n\n使用范例\n\n```java\npublic void doGet(HttpServletRequest request, HttpServletResponse response) {\n    // 返回结果序列化为JSON字符串\n    String content = \"{msg: \\\"'hello'\\\"}\";\n    try {\n        // 调用工具方法按具体策略返回结果\n        CORSResponseUtil.response(request, response, content);\n    } catch (IOException e) {\n        e.printStackTrace();\n    }\n}\n```\n\n#### 低版本代理文件配置\n\n##### 代理文件配置\n\n在服务器放置NEJ代理文件，NEJ代理文件可从[这里](https://github.com/genify/nej/tree/master/res)获取，如果代理文件在服务器的/res/下可直接访问，则代码中无需配置，否则在载入NEJ define.js文件之前做好代理配置\n\n```html\n<script>\n    window.NEJ_CONF = {\n        // 多个域名在这里配置\n        p_frame:['http://a.b.com/path/to/nej_proxy_frame.html']\n    };\n</script>\n<script src=\"/path/to/nej/define.js\"></script>\n```\n\n##### 白名单配置\n\n数据提供方可以通过修改nej\\_proxy\\_frame.html中的白名单来控制允许调用接口的第三方域名，这里主要以正则表达式方式配置whitelist即可\n\n```html\n<script>window.whitelist=[/.*/i];</script>\n```\n\n### _$request\n\n\\_#request接口在util/ajax/xdr模块中实现\n\n|      | 类型 | 描述 |\n| :--  | :--  | :-- |\n| 输入 | String | 请求地址 |\n|      | Object | 配置信息 |\n| 输出 | String | 请求标识 |\n\n配置参数说明\n\n| 参数 | 类型 | 说明 |\n| :--  | :--  | :-- |\n| sync    | Boolean  |  是否同步请求 |\n| type    | String   |  返回数据格式,text/json/xml |\n| data    | Variable |  要发送的数据 |\n| query   | Variable |  查询参数,字符串格式a=b&c=d,对象格式{a:'b',c:'d'} |\n| method  | String   |  请求方式,GET/POST |\n| timeout | Number   |  超时时间,0 禁止超时监测 |\n| headers | Object   |  头信息表 |\n| cookie  | Boolean  |  跨域请求是否带cookie，仅对CORS方式有效 |\n| mode    | Number   |  请求模式,针对跨域请求采用的请求方式 |\n| result  | Object   |  onload回调输入时需包含的额外信息，已处理额外数据，headers - 服务器返回头信息，如{headers:'x-res-0'}或者{headers:['x-res-0','x-res-1']} |\n| onload  | Function |  数据载入回调 |\n| onerror | Function |  请求异常回调 |\n| onbeforerequest | Function  | 请求之前回调 |\n\n请求模式配置说明\n\n* 0 - 自动模式，高版本使用HTML5的CORS协议，低版本采用Frame代理方式\n* 1 - 高版本使用HTML5的CORS协议，低版本采用Flash代理方式\n* 2 - 全部使用Frame代理方式\n* 3 - 全部使用Flash代理方式\n\n代码举例\n\n```javascript\nNEJ.define([\n    'util/ajax/xdr'\n],function(_j){\n    // 从a.b.com载入数据\n    _j._$request(\n        'http://a.b.com/api/get',{\n            type:'json',\n            onload:function(_result){\n                // TODO\n            },\n            onerror:function(_error){\n                // TODO\n            }\n        }\n    );\n});\n```\n\n### _$upload\n\n\\_$upload接口在util/ajax/xdr模块中实现\n\n|      | 类型 | 描述 |\n| :--  | :--  | :-- |\n| 输入 | HTMLFormElement | 表单对象，待上传的文件及目标地址信息封装在此对象中 |\n|      | Object | 配置信息 |\n| 输出 | String | 请求标识 |\n\n配置参数说明\n\n| 参数 | 类型 | 说明 |\n| :--  | :--  | :-- |\n| type    | String   |  返回数据格式\n| query   | Variable |  查询参数\n| mode    | Number   |  跨域类型，0/2，见[_$request](#_$request)接口说明\n| headers | Object   |  头信息\n| cookie  | Boolean  |  跨域请求是否带cookie，仅对CORS方式有效\n| onload  | Function |  数据载入回调\n| onerror | Function |  请求异常回调\n| onuploading | Function |  上传进度回调\n| onbeforerequest | Function |  请求之前回调\n\n代码举例\n\n```html\n<form id=\"upload\" name=\"upload\" action=\"http://123.163.com:3000/xhr/uploadCallback\">\n   <input type=\"text\" id=\"progress\" />\n   <!-- 低版本轮询进度接口 -->\n   <input type=\"hidden\" name=\"nej_mode\" value=\"2\" />\n   <input type=\"hidden\" name=\"nej_query\" value=\"http://123.163.com:3000/xhr/progress\" />\n</form>\n```\n\n```javascript\nNEJ.define([\n    'util/ajax/xdr'\n],function(_j){\n    _j._$upload('upload',{\n        mode:2,\n        cookie:true,\n        onuploading:function(_data){\n            // 后台处理http://123.163.com:3000/xhr/progress，返回一个json对象\n            // 前台会去轮询此接口获取进度\n            if(!!_data.total&&_data.progress){\n                _progress.value = _data.progress;\n            }\n        },\n        onload:function(_url){\n            // 此前会把进度轮询终止掉。如果要显示进度100%，可在此设置一次\n            // 后台处理http://123.163.com:3000/xhr/uploadCallback，返回url\n            // 文件上传完成的回调,url为返回的地址\n        }\n    });\n});\n```\n"
  },
  {
    "path": "doc/CACHE.md",
    "content": "# 前端存储机制\n\n## 概述\n\n\n\n## 内存缓存\n\n\n\n\n## 本地存储\n\n\n\n\n## 本地数据库\n\n\n\n\n"
  },
  {
    "path": "doc/DEPENDENCY.md",
    "content": "# 依赖管理系统\n\n## 概述\n\n随着前端系统的日渐复杂，系统所依赖的文件越来越多，单纯的依靠人肉管理已经无法满足高品质系统的需求了，为了便于开发者管理、老系统平滑升级迁移，NEJ提供了一套文件依赖管理系统，本系统主要特性包括：\n\n* 安全沙箱：文件定义的模块运行在自己的执行环境中，通过返回控制对外开放的接口\n* 依赖管理：管理文件之间的依赖关系，包括非脚本的资源文件\n* 依赖注入：文件依赖的其他资源可以通过返回结果注入给其依赖文件\n* 平滑升级：无脚本侵入，只需通过配置即可在老系统中实现依赖管理\n* 打包发布：提供优化输出[打包工具](https://github.com/genify/toolkit.git)，分离依赖系统，减少依赖对线上产品的影响\n\n## 使用\n\n页面引入依赖库文件，配置参数通过define.js的查询参数输入\n\n```html\n<script src=\"/path/to/nej/define.js?pro=./\"></script>\n```\n\n脚本文件定义，为防止与其他加载器命名冲突，NEJ使用NEJ.define接口定义文件执行函数\n\n```javascript\nNEJ.define([\n    'base/element',\n    'pro/extend/util',\n    '/path/to/file.js',\n    '{platform}patch.js',\n    'text!/path/to/file.css',\n    'text!/path/to/file.html'\n],function(e,u,t,h,css,html,p,o,f,r){\n\n    // TODO something\n\n    // 返回结果可注入给其他文件\n    return p;\n});\n```\n\n## 配置\n\nNEJ的依赖管理系统配置信息通过define.js的查询参数输入，打包时也会根据这些参数配置做相应处理\n\n系统保留单字母命名的参数配置，预置的配置参数如：g、c、d、p\n\n### 预置配置\n\n#### g=[true|false]\n\n配置项目中是否存在全局的define函数，默认为false，如果配置为true则项目中必须使用NEJ.define来使用本依赖管理系统，否则如果项目没有定义额外的define函数则可以使用define函数来使用此依赖系统\n\n```html\n<script src=\"/path/to/nej/define.js?g=true\"></script>\n```\n\n#### c=[gbk|utf-8|…]\n\n配置项目编码格式，依赖载入的脚本编码格式会设置为此参数配置的信息，打包输出也会参考此参数进行输出，默认为utf-8，如果配置为其他编码格式则需保证项目的相关文件的编码必须统一为此配置的编码格式\n\n```html\n<script src=\"/path/to/nej/define.js?c=gbk\"></script>\n```\n\n#### d=/patch/to/dep.js\n\n配置第三方库或者遗留项目文件的依赖关系，具体使用可参看NEJ.deps接口的说明\n\n```html\n<script src=\"/path/to/nej/define.js?d=./dep.js\"></script>\n```\n\n#### p=td|gk|wk\n平台配置参数，见以下[平台配置](#平台配置)章节说明\n\n\n### 路径配置\n\n文件定义时指定的路径可以通过路径配置的变量来指定前缀，如路径配置时指定了变量A，则文件定义时可以直接使用A或者”{A}”来表示A指定的路径前缀。\n\n```html\n<script src=\"/path/to/nej/define.js?A=../web/js/\"></script>\n```\n\n```javascript\nNEJ.define([\n    'A/extend/util',\n    '{A}extend/util.js'\n],function(u1,u2){\n\n    // 这里需要注意的是如果使用{A}形式需要加后缀.js\n    // 这里两种方式引入的为同一个文件都是 ../web/js/extend/util.js 文件\n\n});\n```\n\n系统默认预置了lib、pro、platform的路径配置\n\n#### lib\n\nNEJ框架路径配置名称为”lib”，文件定义和依赖时可直接使用”{lib}”来表示框架的路径，默认此路径为外联的define.js文件所在的路径\n\n```html\n<script src=\"/path/to/nej/define.js\"></script>\n```\n\n```javascript\nNEJ.define([\n    'base/element',\n    'lib/base/element',\n    '{lib}base/element.js'\n],function(e1,e2,e3){\n\n    // 这里解析出来的lib为 /path/to/nej/\n    // 以上三种方式访问的为同一个文件都是 /path/to/nej/base/element.js 文件\n\n});\n\n```\n\n#### pro\n\n项目脚本根路径配置名称为“pro”，文件定义和依赖时可直接使用pro或“{pro}”来表示脚本根路径，此配置信息可以通过外联的define.js路径中的查询串进行配置。如果没有自定义配置则默认相对于当前页面访问路径的“../javascript/”路径。\n\n```html\n<script src=\"/path/to/nej/define.js?pro=./\"></script>\n```\n\n```javascript\nNEJ.define([\n    'pro/api/element',\n    '{pro}/api/element.js'\n],function(e1,e2){\n\n    // 以上两种方式访问的为同一个文件都是 ./api/element.js 文件\n\n});\n\n```\n\n#### platform\n\n控件依赖补丁名称为“platform”，只用于文件依赖，使用“{platform}xxx.js”来表示控件依赖的补丁文件，会解析为依赖xxx.js和xxx.patch.js两个文件。xxx.js为W3C/ES规范实现方式，提供所有标准平台支持的公用部分，xxx.patch.js通过NEJ.patch接口提供不同平台对这些接口的特有实现逻辑，这部分内容的详细说明参阅《NEJ平台适配系统》\n\n```\n  widget\n    | - element.js\n    | - platform\n            | - element.js\n            | - element.patch.js\n```\n\n```javascript\nNEJ.define([\n    '{platform}/element.js'\n],function(e1){\n\n    // 这里会自动载入 ./platform/element.js 和 ./platform/element.patch.js 文件\n\n});\n\n```\n\n#### 自定义路径\n\n其他自定义路径可以通过引入define.js文件时作为查询参数输入进行配置，如自定义com路径，则可以通过以下方式进行配置（配置路径中以”./”、”../”起始的相对路径相对于当前地址栏路径）\n\n```html\n<script src=\"/path/to/nej/define.js?com=../js/\"></script>\n```\n\n```javascript\nNEJ.define([\n    'com/api/util',\n    '{com}api/util.js'\n],function(u1,u2){\n\n    // 这里两种方式引入的为同一个文件都是 ../js/api/util.js 文件\n\n});\n```\n\n### 平台配置\n\n平台参数在开发及打包过程中都会使用，框架支持平台参数的配置通过define.js路径上查询串中的p参数输入。\n\n平台配置信息，此配置又分两类基本配置：补丁配置和混合配置，因为混合模式下使用的浏览器引擎固定，因此当配置中出现混合类型的配置时忽略补丁配置的值。\n\n如果在引入依赖定义库时未指定平台信息则表示系统需对全平台浏览器支持。\n\n关于平台配置相关的详细内容可参阅《NEJ平台适配系统》\n\n#### 补丁配置\n\n主要用来修正浏览器平台对接口及控件的支持，按照目前浏览器引擎划分，参数值由一个或者多个平台标识组成，标识支持如下所示：\n\n| 标识  | 说明 |\n| :---  | :--- |\n| gk    | 以gecko为核心的浏览器平台，如firefox等 |\n| wk    | 以webkit为核心的浏览器平台，如chrome、safari等 |\n| td    | 以trident为核心的浏览器平台，如IE、360、maxthon等 |\n| td-0  | 以trident为核心的浏览器平台，且引擎内核版本大于等于3.0，即IE>=7 |\n| td-1  | 以trident为核心的浏览器平台，且引擎内核版本大于等于7.0，即IE>=10 |\n\n```html\n<script src=\"/path/to/nej/define.js?p=wk|gk|td\"></script>\n```\n\n#### 混合配置\n\n主要用于混合开发模式下对native接口的适配，按照native平台划分，参数值由一个标识组成，多个标识则以识别的第一个标识为准，标识支持如下所示：\n\n| 标识 | 说明 |\n| :--- | :--- |\n| cef       | 基于cef框架混合应用，主要针对桌面应用 |\n| ios       | ios平台混合应用，如iphone应用、ipod应用、ipad应用等 |\n| win       | windows phone平台混合应用 |\n| android   | android平台混合应用 |\n\n```html\n<script src=\"/path/to/nej/define.js?p=cef\"></script>\n```\n\n\n## 接口\n\n以下所有接口均使用NEJ作为名字空间，如define接口使用时用NEJ.define\n\n### define\n\n文件定义接口，并指定当前脚本执行所需的其他依赖文件，文件路径规则\n\n* 完整的文件路径，如 http://a.b.com/patch/to/file.js\n* 使用{}标识配置参数，如{root}file.js\n* 直接使用非{}标识配置参数，此时不能加.js后缀，系统自动加.js后缀，如 root/file\n* NEJ库文件可以省略lib标识，如base/element，等价于 lib/base/element，等价于 {lib}base/element.js\n* 其他文本资源采用text!前缀标识，如text!/path/to/file.css，注意开发时如果资源是跨域的请设置好浏览器XHR的跨域支持\n* JSON资源采用json!前缀标识，如json!/path/to/data.json，注意开发时如果资源是跨域的请设置好浏览器XHR的跨域支持\n* Regular模板资源采用regular!前缀标识，如regular!/path/to/file.html，注意开发时如果资源是跨域的请设置好浏览器XHR的跨域支持\n* 路径以 ./ 或者 ../ 开始的相对路径则相对于当前脚本文件的路径，如 ./util.js\n\n执行函数注入参数说明\n\n* 注入依赖列表中各文件对应的返回结果\n* 注入额外四个参数，依次为p、o、f、r，其中\n  * p为输出结果集空间，用于注入到其他执行函数中的内容\n  * o为对象实例，即{}，用于处理对象默认值，如 var x = options||o;\n  * f为函数实例，返回false，用于处理方法默认值，如 var func = x.onready||f;\n  * r为数组实例，即[]，用于处理数组默认值，如 var arr = options.list||r;\n\n接口说明\n\n|      | 类型 | 描述 |\n| :--- | :--- | :--- |\n| 输入 | String   |   可选，当前文件路径 |\n|      | Array    | 可选，依赖的其他文件路径 |\n|      | Function | 可选，当前文件需要执行的脚本，依赖文件的返回结果依次注入到该函数中 |\n| 输出 | Object   |   对外开放的接口，可注入到依赖该文件的其他文件执行函数中 |\n\n```javascript\nNEJ.define([\n    'util/ajax/tag',\n    'util/template/jst'\n],function(j,e,p,o,f,r){\n\n    // j 为 util/ajax/tag 文件导出的接口集合\n    // e 为 util/template/jst 文件导出的接口集合\n\n    // 用于注入到其他文件执行函数中的接口\n    p.api = function(){\n\n    };\n\n    // TODO something\n\n    return p;\n});\n```\n\n### patch\n\n平台补丁配置接口，用于针对不同平台做修正逻辑，平台支持TR|WR|GR，没有比较操作符表示支持当前内核所有release版本，平台引擎标识说明如下\n\n| 标识  | 说明 |\n| :---  | :--- |\n| T     | Trident引擎，如IE |\n| W     | Webkit引擎，如chrome |\n| G     | Gecko引擎，如firefox |\n\n内置的Trident引擎版本对应的IE版本关系\n\n| Trident版本 | IE版本 |\n| :---  | :--- |\n| 2.0 | 6 |\n| 3.0 | 7 |\n| 4.0 | 8 |\n| 5.0 | 9 |\n| 6.0 | 10 |\n| 7.0 | 11 |\n\n接口说明\n\n|      | 类型 | 描述 |\n| :--- | :--- | :--- |\n| 输入 | String   |   必须，平台的判断条件，如2=<TR<4 |\n|      | Array    | 可选，依赖文件列表，规则同define接口定义的文件路径 |\n|      | Function | 可选，当前条件下需要执行的脚本 |\n| 输出 | Void     | 无 |\n\n```javascript\nNEJ.define([\n    './hack.js'\n],function(h){\n    // 针对trident平台的处理逻辑\n    NEJ.patch('TR',function(){\n        // TODO\n    });\n    // 针对gecko平台的处理逻辑\n    NEJ.patch('GR',[\n        './hack.firefox.js'\n    ],function(fh){\n        // TODO\n    });\n    // 针对IE6平台的处理逻辑\n    NEJ.patch('TR==2.0',['./hack.ie6.js']);\n    // 针对IE7-IE9的处理逻辑\n    NEJ.patch('3.0<=TR<=5.0',function(){\n        // TODO\n    });\n\n    // 这里必须同hack.js文件的返回值一致\n    return h;\n});\n```\n\n### deps\n\n通过配置来管理依赖，对于历史遗留项目或者使用了非AMD规范的第三方库如需引入依赖管理，可以通过此接口先配置依赖关系表，后期维护可直接使用依赖方式进行\n\n开发阶段会全部依赖，发布只提取页面使用的脚本\n\n接口说明\n\n|      | 类型  | 描述 |\n| :--- | :--- | :--- |\n| 输入 | Array | 可选，依赖映射表 |\n|      | Array | 可选，入口屏蔽文件列表 |\n| 输出 | Void  | 无 |\n\n假设系统依赖文件配置表为 deps.js， 文件内容如下\n\n```javascript\nNEJ.deps({\n    '{pro}a.js':['{pro}b.js','{pro}c.js','{pro}d.js'],\n    '{pro}b.js':['{pro}c.js','{pro}e.js'],\n    '{pro}c.js':['{pro}d.js','{pro}e.js','{pro}a.js'],\n    '{pro}d.js':['{pro}e.js'],\n    '{pro}f.js':['{pro}a.js']\n},[\n    '{pro}f.js'\n]);\n```\n\n则页面引入方式可用以下形式\n\n```html\n<script src=\"/path/to/nej/define.js?d=./deps.js&pro=./\"></script>\n<script src=\"./f.js\"></script>\n<script>\n    NEJ.define([\n        '{pro}a.js',\n        '{pro}e.js'\n    ],function(){\n        log('app');\n    });\n</script>\n```\n\n## 循环依赖\n\n当依赖链出现了环时我们就认为出现了循环依赖，依赖管理系统对于循环依赖的处理分两种情况\n\n如下箭头方向表示文件的依赖，如 a.js 依赖 b.js\n\n```\n   a.js  ->  b.js  ->  a.js\n```\n\n* 强依赖：依赖文件之间的接口调用直接出现在文件定义函数中，避免代码出现强依赖，执行过程会出异常\n* 弱依赖：依赖文件之间的接口调用出现在文件定义函数内部的某个接口中，允许出现弱依赖，可以正常处理\n\n### 强依赖\n\n在define接口中输入的执行函数里直接调用了依赖列表中的其他文件中的API的情况\n\na.js文件\n\n```javascript\nNEJ.define([\n    './b.js'\n],function(b,p){\n\n    // 在此函数中直接调用了b的接口\n    var result = b.api();\n\n    p.api = function(){\n        // TODO\n        return 'aaaaa';\n    };\n\n    return p;\n});\n```\n\nb.js文件\n\n```javascript\nNEJ.define([\n    './a.js'\n],function(a,p){\n\n    // 在此函数中直接调用了a的接口\n    var result = a.api();\n\n    p.api = function(){\n        // TODO\n        return 'bbbbbb';\n    };\n\n    return p;\n});\n```\n\n### 弱依赖\n\n在define接口中输入的执行函数里没有直接调用依赖列表中的其他文件中的API，所有对其他文件的API的调用均在当前文件提供的API中调用的情况\n\na.js文件\n\n```javascript\nNEJ.define([\n    './b.js'\n],function(b,p){\n\n    // 在其他API中调用了b的接口\n    p.doSomething = function(){\n        var result = b.api();\n    };\n\n    p.api = function(){\n        // TODO\n        return 'aaaaa';\n    };\n\n    return p;\n});\n```\n\nb.js文件\n\n```javascript\nNEJ.define([\n    './a.js'\n],function(a,p){\n\n    // 在其他API中调用了a的接口\n    p.doSomething = function(){\n        var result = b.api();\n    };\n\n    p.api = function(){\n        // TODO\n        return 'bbbbbb';\n    };\n\n    return p;\n});\n```\n"
  },
  {
    "path": "doc/DISPATCHER.md",
    "content": "# 模块调度系统\n\n## 概述\n\n随着WEB技术的发展，使用WEB技术构建富应用的场景越来越多，相比于纯Native技术，利用WEB技术构建富应用有其先天优势，如良好的跨平台特性、高效的构建及需求响应效率、更低的资源成本投入等，随着移动互联网的快速崛起、硬件设备的不断升级换代，WEB构建的应用体验将会越来越接近于纯Native的体验\n\n使用WEB技术构建单页富应用在混合应用技术中使用的越来越多，此类应用复杂度要高于一般网站类型的WEB系统，采用模块化技术可用来将复杂系统拆分为若干简单子系统，同时所有子系统又需兼具低耦合，高可重组性，实际案例如：\n\n* 移动混合应用（如 [网易云相册IPad版](http://photo.163.com/cloudphotos/)、[Lofter](http://www.lofter.com/app)等）\n* 桌面混合应用（如 [网易云音乐PC版](http://music.163.com/#/download)、[网易闪电邮](http://flashmail.163.com/)等）\n\nNEJ提供了一套模块调度系统 用于支持单页富应用的系统架构、模块拆分和重组、模块调度管理 等功能\n\n## 模块\n\n这里我们定义的模块是指从系统中拆分出来的可与用户进行交互完成一部分完整功能的独立单元\n\n### 模块组成\n\n因为这里描述的模块可独立与用户完成交互功能，因此模块会包含以下元素\n\n* 样式：定义模块的效果\n* 结构：定义模块的结构\n* 逻辑：实现模块的功能\n\n以上元素对于一个WEB系统开发者来说并不陌生，而我们只需要寻求一种形式将这些内容封装起来即可\n\n### 模块封装\n\n从模块的组成我们可以看到从系统中分离出来的模块可能会长成这个样子，比如module.html就是我们分离出来的一个模块，当然这里也可以用脚本文件封装，样式和结构采用注入形式，我们这里以html文件封装举例\n\n```html\n<!-- 模块样式 -->\n<style>\n    .m-mdl-1 .a{color:#aaa;}\n    .m-mdl-1 .b{color:#bbb;}\n\n    /* 此处省略若干内容 */\n</style>\n\n<!-- 模块结构 -->\n<div class=\"m-mdl-1\">\n  <p class=\"a\">aaaaaaaaaaaaaaaaaaa</p>\n  <p class=\"b\">bbbbbbbbbbbbbbbbbbb</p>\n\n  <!-- 此处省略若干内容 -->\n</div>\n\n<!-- 模块逻辑 -->\n<script>\n    (function(){\n        var a = 'aaa';\n        var b = 'bbb';\n\n        // 此处省略若干内容\n    })();\n</script>\n```\n\n而这个模块在用户需要时加载到客户端，并展现出来跟用户进行交互，完成功能；但是我们会发现如果系统预加载了此模块或者模块在parse时这些内容会被直接执行，而这个结果并不是我们需要的，因此我们需要将模块的各元素文本化处理，文本化处理有多种方式，如作为文本script、textarea等标签内容，因此module.html里的模块我们可以封装成如下样子，以textarea举例：\n\n```html\n<!-- 模块样式 -->\n<textarea name=\"css\">\n    .m-mdl-1 .a{color:#aaa;}\n    .m-mdl-1 .b{color:#bbb;}\n\n    /* 此处省略若干内容 */\n</textarea>\n\n<!-- 模块结构 -->\n<textarea name=\"html\">\n    <div class=\"m-mdl-1\">\n      <p class=\"a\">aaaaaaaaaaaaaaaaaaa</p>\n      <p class=\"b\">bbbbbbbbbbbbbbbbbbb</p>\n\n      <!-- 此处省略若干内容 -->\n    </div>\n</textarea>\n\n<!-- 模块逻辑 -->\n<textarea name=\"js\">\n    (function(){\n        var a = 'aaa';\n        var b = 'bbb';\n\n        // 此处省略若干内容\n    })();\n</textarea>\n```\n\n## 管理依赖\n\n从系统中拆分出来的模块之间是存在有一定关系的，如一个模块的呈现必须依赖另外一个模块的呈现，下面我们会以一个简单的例子来讲解模块之间的依赖管理，如下图是我们的一个单页富应用\n\n![单页富应用范例](http://nej.netease.com/images/sample.gif)\n\n从上图不难看出整个系统包含以下几部分内容：\n\n* 日志管理\n\n  * 日志：日志列表，可切换收件箱/草稿箱/回收站/标签\n  * 标签：标签列表，可转至日志按标签查看列表\n\n* 博客设置\n\n  * 账号管理\n\n    * 基本资料：用户基本资料设置表单\n    * 个人经历：个人经历填写表单\n\n  * 权限设置：权限设置表单\n\n而这些模块之间的层级关系则如下所示\n\n![模块层级结构图](http://img0.ph.126.net/7ixXaTU-uFtbe0pKCWCgPA==/6597270977286264717.png)\n\n针对交互式系统的这种层级架构典型的模式可以参阅[PAC（Presentation－Abstraction－Control）模式](http://en.wikipedia.org/wiki/Presentation%E2%80%93abstraction%E2%80%93control) 或者 [HMVC（Hierarchical model–view–controller）模式](http://en.wikipedia.org/wiki/Hierarchical_model%E2%80%93view%E2%80%93controller)\n\n然而在WEB交互式系统的实践过程中我们发现这种模式会存在一些缺陷：\n\n* 由于每个父模块自己维护了所有的子模块，因此父子模块之间耦合性过强，父模块必须耦合所有子模块\n* 由于模块之间不能越级调用，因此子模块需要其他模块协助时必须层层向上传递事件，如果层级过深则会影响到系统效率\n* 模块的增删等变化导致的变更涉及的影响较大，删除中间节点上的模块可能导致相邻的若干模块的变更\n* 多人协作开发系统时存在依赖关系的模块会导致开发人员之间的紧密耦合\n\n在这里我们给出了一种基于模块标识的依赖管理配置方案，可以彻底的将模块进行解耦，每个模块可以独立完整的完成自己的交互功能，而系统的整合则可以通过配置的方式灵活的重组各模块，模块的增删操作只需修改配置即可完成，而无需影响到具体业务逻辑\n\n下文我们会通过以上例子来讲解此方案的原理和实际操作方式\n\n### 模块标识\n\n因为本方案会基于模块标识做配置，因此在介绍方案之前我们先介绍一下模块标识，这里我们给模块标识取名为**UMI**（Uniform Module Identifier）统一模块标识，下文简称UMI，遵循以下规则约定\n\n* 格式同URI的Path部分，如 /m/m0/\n* 必须以“/”符开始\n* 私有模块必须以“/?”开始\n* 承载模块的依赖关系，如 /m/m0/ 和 /m/m1/ 表明这两个标识对应模块的父模块标识均为 /m\n\n每个UMI均可唯一标识一个模块及模块在系统中的依赖关系，在模块章节我们介绍了一个模块可以用一个html进行封装，因此我们可以得到以下结果\n\n![UMI与模块地址映射关系图](http://img0.ph.126.net/DCSPjxzVgjlgc8B983YSSg==/2673167853921558567.png)\n\n每个UMI均可映射到一个模块实现文件，这样我们就可以将模块从具体实现中解耦出来，对模块的增删修改操作只需调整UMI和模块文件的映射关系即可，而无需涉及具体业务逻辑的修改\n\n### 模块依赖\n\n在解决了模块与实现分离的问题后，我们接下来需要将层级式的模块扁平化来解耦模块之间的依赖关系\n\n回到前面的例子，模块之间的层级关系如下图所示\n\n![模块层级关系图](http://img1.ph.126.net/NFbfUjokCb1KsI8tCj04xw==/6608203421400487879.jpg)\n\n如果我们将图中的依赖关系进行抽象分离后可以发现所有的模块即可呈现扁平的状态\n\n![模块关系分离图](http://img1.ph.126.net/XByNuSHTyJ_OzmAFIcqGKQ==/6608480498329578217.png)\n\n而对于模块之前的依赖关系的管理在所有系统中都是一致的，但是每个模块的具体功能实现是由系统来决定的，不同的系统是截然不同的，因此本方案提供的解决方案主要是用来维护模块之间的依赖关系的\n\n从上图我们可以比较清楚的看到模块之间的依赖关系呈现树状结构，因此我们会以树的结构来组织维护模块之间的依赖关系，我们称之为依赖关系树，而当我们将这棵树上的任意节点与根节点之间的路径用“/”分隔序列化后发现刚好与我们提供的UMI是匹配的，因此组成系统的模块的UMI可以跟依赖关系树的节点一一对应起来，如下图所示\n\n![依赖关系树节点序列化成UMI](http://img2.ph.126.net/cu36voh3bRXFx530aW6nkg==/6608921402492317376.png)\n\n在模块标识章节我们介绍了UMI与模块封装文件可以相互映射，因此依赖关系树上的节点可以直接与模块的实现文件做一一对应，如下图所示\n\n![依赖关系树映射模块实现文件](http://img1.ph.126.net/6Pfkz1_4dd32jnL60QQ1Kw==/6608598146073751639.png)\n\n至此，我们将垂直层级依赖的模块通过依赖关系树分解成了无任何关系的扁平模块结构\n\n### 模块组合\n\n模块只需要有个呈现容器即可渲染出来，因此模块如果需要能够做任意组合，只需将模块分成两种类型：提供容器的模块和使用容器的模块即可，当然一个模块可同时兼具提供容器和使用容器的功能，提供容器的模块和使用容器的模块可任意组合\n\n![模块组合](http://img2.ph.126.net/D446SK2cBk_aGZFLVRwIew==/3669307796500606643.png)\n\n对于模块组合的配置代码范例\n\n```javascript\n'/m/blog/list/':{\n    module:'module/layout/blog.list/index.html',\n    composite:{\n        box:'/?/blog/box/',\n        tag:'/?/blog/tag/',\n        list:'/?/blog/list/',\n        clazz:'/?/blog/class/'\n    }\n}\n```\n\n## 调度策略\n\n在将模块扁平化后，各模块就可以安排给不同的开发人员进行功能实现和测试了，各模块完成后根据依赖关系树进行系统整合，完成系统整合后各模块会遵循一定的调度策略进行调度\n\n### 模块状态\n\n根据模块调度的阶段划分，模块的状态可以分为以下四个阶段：\n\n* 模块构建：构建模块结构\n* 模块显示：将模块渲染到指定的容器中\n* 模块刷新：根据外界输入的参数信息获取数据并展示（这里主要做数据处理）\n* 模块隐藏：模块放至内存中，回收由刷新阶段产生的额外结构\n\n调度策略主要控制模块在这几个阶段之间的转换规则\n\n### 模块显示\n\n当用户请求显示一个模块时各模块会遵循以下步骤进行调度，假设请求显示 /m/blog/list/ 模块\n\n![显示调度策略](http://img1.ph.126.net/ip4S9-mTCAH943VGwXZ1OQ==/6619563575537201227.png)\n\n1. 检查目标节点到根节点路径上注册的模块，如果注册的是模块的实现文件地址，则请求载入模块实现文件\n2. 如果节点所在的模块的所有祖先节点已显示，则当前模块可被显示出来，否则等待祖先模块的显示调度\n3. 模块载入后根据第二步骤原则尝试调度目标模块的显示\n\n### 模块切换\n\n当用户从一个模块切换到另外一个模块时各模块遵循以下步骤调度，假设从 /m/blog/list/ 切换到 /m/setting/account/edu/ 模块\n\n![模块切换](http://img0.ph.126.net/ca9IdYk2ezLL-zN8vRqI4Q==/6619574570653479153.png)\n\n1. 查找源模块与目标模块的公共父节点\n\n   ![查找公共模块](http://img2.ph.126.net/G36CYcFsck1w8Uf0k7oOIw==/6608672912864439374.png)\n\n2. 从源节点到公共节点之间的模块调度隐藏操作\n\n   ![隐藏模块](http://img0.ph.126.net/kCydlPd-q7yUIQ2rc65Eyg==/6608818048399307052.png)\n\n3. 从根节点到公共节点之间的模块调度刷新操作\n\n   ![刷新模块](http://img2.ph.126.net/sN7NPW5etJ0FVjv-TyBL9w==/6608677310910950450.png)\n\n4. 从公共节点到目标节点之间的模块调度显示操作\n\n   ![显示模块](http://img1.ph.126.net/DwnLyinZy9ZG8IX_uwOmsg==/6599306173308730570.png)\n\n## 消息通道\n\n大部分时候我们不需要模块之前的消息通信，实践中也存在一些特殊情况会需要模块之前的消息通信，这里提供两种方式的消息通讯\n\n* 点对点的消息：一个模块发送消息时明确指定目标模块的UMI\n* 观察订阅消息：一个模块可以对外申明发布了什么样的消息，有需要的模块可以订阅该模块UMI上的消息\n\n## 实例解析\n\n这部分我们用上面的具体实例讲解如何使用NEJ的模块调度系统来拆分一个复杂系统、开发测试模块、整合系统\n\n### 系统分解\n\n#### 绘制层级关系图\n\n当我们拿到一个复杂系统时根据交互稿可以绘制出组成系统的模块的层级关系图，并确定系统对外可访问的模块\n\n![模块层级关系图](http://img1.ph.126.net/UmNMLNzb-Vjdtv8skT8kqg==/6608742182096989774.png)\n\n#### 抽象依赖关系树\n\n从模块的层级关系图中我们可以非常方便的抽象出模块的依赖关系树\n\n![抽象依赖关系树](http://img1.ph.126.net/BK5_LhDhh01addpDJuY4Yw==/6619331578583739475.png)\n\n将抽象出来的依赖关系树根据UMI规则进行格式化，格式化的主要操作包括\n\n* 增加一个名称为“/”的根结点（也可将“m”结点改为“/”）\n* 每个结点增加“/”的子节点作为默认节点\n\n![格式化依赖关系树](http://img2.ph.126.net/5b3ByaubY0XFOlnU1PZHAw==/6619382156118617138.png)\n\n至此输出的依赖关系树，具有以下特性：\n\n* 任何一个结点（除根结点外）到根结点路径上的结点名称用“/”分隔组合起来即为结点的UMI值，如list结点的UMI值为/m/blog/list\n* 任何结点上的模块都依赖于他祖先结点（注册有模块）上的模块存在，如blog结点和list结点均注册有模块，则list结点上的模块显示必须以blog结点上的模块的显示为先决条件\n\n#### 确定对外模块注册节点\n\n五个对外可访问的模块：日志、标签、基本资料、个人经历、权限设置，在依赖关系树中找到合适的结点（叶子结点，层级关系树在依赖关系树中对应的结点或“/”结点）来注册对外可访问的模块\n\n![对外模块注册节点](http://img0.ph.126.net/vC28JzPSddgzZdpEAeBZ2w==/6619485510211628655.png)\n\n#### 确定布局模块注册节点\n\n从可访问模块注册的结点往根结点遍历，凡碰到两模块交叉的结点即为布局模块注册结点，系统所需的组件相关的模块可注册到根结点，这样任何模块使用的时候都可以保证这些组件已经被载入\n\n![布局模块注册节点](http://img1.ph.126.net/Jjp0GCDfh2eXvaxJvhiCeQ==/6619215030351195733.png)\n\n#### 映射模块功能\n\n原则：结点的公共父结点实现结点上注册的模块的公共功能\n\n举例：blog结点和setting结点的公共父结点为m结点，则我们可以通过切换blog模块和setting模块识别不变的功能即为m模块实现的功能，同理其他模块\n\n![功能映射](http://img2.ph.126.net/64xhHIfGy4qdQKSV5Bym-g==/2679360303409193237.png)\n\n#### 分解复杂模块\n\n进一步分解复杂模块，一般需要分解的模块包括：\n\n* 可共用模块，比如日志列表，可以在日志管理页面呈现，也可以在弹层中显示\n* 逻辑上无必然联系的模块，如日志模块中日志列表与右侧的按标签查看的标签列表之间没有必然的联系，任何一个模块的移除或添加都不会影响到另外一个模块的业务逻辑\n\n![分解复杂模块](http://img1.ph.126.net/wRM1uAxQDRFhfAzlNw8b5Q==/6599274287471525959.png)\n\n至此我们可以得到两棵系统分解后的依赖关系树\n\n对外模块依赖关系树\n\n![对外模块依赖关系树](http://img2.ph.126.net/6yAKfH-sST3-RGc0xIxU2g==/6608788361585356880.png)\n\n私有模块依赖关系树\n\n![私有模块依赖关系树](http://img1.ph.126.net/KgimU46Zn4ZnUtxiBrXdKw==/6608191326772584502.png)\n\n#### 绘制模块功能规范表\n\n本例中为了说明分解过程将所有可分解的模块都做了分解，实际项目看具体情况，比如这里的/m模块组合的/?/tab/模块的功能可以直接在/m模块中实现，而不需要新建一个/?/tab/模块来实现这个功能\n\n规范表范例如下所示\n\n![功能规范表](http://img1.ph.126.net/e_0ZFwbefuXT5bZ6bq17Rg==/1496320976294650210.png)\n\n### 构建目录\n\n#### 项目目录\n\n项目目录的构建如下图所示\n\n![项目目录](http://img0.ph.126.net/7mfjeInfGILw-tWQznxxLA==/6608777366469080397.png)\n\n各目录说明\n\n```\nwebroot                    项目前端开发相关目录\n   |- res                  静态资源文件目录，打包时可配置使用到该目录下的静态资源带版本信息\n   |- src                  前端源码目录，最终发布时该目录不会部署到线上\n       |- html\n            |- module      单页面模块目录，系统所有模块的实现均在此目录下\n            |- app.html    单页面入口文件\n```\n\n#### 模块单元目录\n\n根据模块封装规则一个模块单元由以下几部分组成：\n\n* 模块测试：模块实现的功能可以通过模块测试页面独立进行测试\n* 模块结构：模块所涉及的结构分解出来的若干模板集合\n* 模块逻辑：根据模块规范实现的模块业务逻辑，从模块基类继承\n* 模块样式：模块特有的样式，一般情况下这部分样式可以直接在css目录下实现\n\n结构范例如下所示\n\n![模块单元目录](http://img0.ph.126.net/o6dTV8RpqAtS63zxdz8sEg==/6608917004445806742.png)\n\n至此我们可以得到所有模块的目录结构如下所示\n\n![模块目录结构](http://img0.ph.126.net/2cMlaKsMBzOfAPPdH9IzkA==/6608797157678379135.png)\n\n### 模块实现\n\n#### 结构\n\n这里我们假设系统的静态页面已经做完，这里的模块实现只是在原有结构的基础上进行结构分解和业务逻辑的实现，结构部分内容主要将模块相关的静态结构拆分成若干NEJ的模板，注意：\n\n* 模板中的外联资源如css，js文件地址如果使用的是相对路径则均相对于模块的html文件路径\n* 模板集合中的外联资源必须使用@TEMPLATE标记标识，这个在后面打包发布章节会详细介绍\n\nNEJ模板说明\n\n![NEJ模板](http://img2.ph.126.net/W_RhwYyx4kbPPGMpcVoUwQ==/6608414527633039667.png)\n\n模块结构举例\n\n```html\n<meta charset=\"utf-8\"/>\n\n<textarea name=\"txt\" id=\"m-ifrm-module\">\n  <div class=\"n-login\">\n    <div class=\"iner j-flag\">\n      <span class=\"cls j-flag\">×</span>\n      <span class=\"min j-flag\">－</span>\n    </div>\n    <div class=\"cnt j-cnt\"></div>\n  </div>\n</textarea>\n\n\n<textarea name=\"css\" data-src=\"./index.css\"></textarea>\n<textarea name=\"js\" data-src=\"./index.js\"></textarea>\n\n```\n\n#### 逻辑\n\n依赖util/dispatcher/module模块，从\\_$$ModuleAbstract扩展一个项目的模块基类，完成项目中模块特有属性、行为的抽象\n\n```javascript\n/*\n * ------------------------------------------\n * 项目模块基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/klass',\n    'util/dispatcher/module'\n],function(_k,_t,_p){\n    // variable declaration\n    var _pro;\n    /**\n     * 项目模块基类对象\n     * @class   {_$$Module}\n     * @extends {_$$ModuleAbstract}\n     * @param   {Object}  可选配置参数，已处理参数列表如下所示\n     */\n    _p._$$Module = _k._$klass();\n    _pro = _p._$$Module._$extend(_t._$$ModuleAbstract);\n    /**\n     * 操作\n     * @param  {Object}\n     * @return {Void}\n     */\n    _pro.__doSomething = function(_args){\n        // TODO\n    };\n\n    // TODO\n\n    return _p;\n});\n```\n\n根据模块状态的划分，我们在实现一个模块时需要实现以下几个接口\n\n![模块各阶段接口](http://img0.ph.126.net/8XyKVwG3dzG0dK59qteZFw==/6619467918025585071.png)\n\n各阶段对应的接口：\n\n* 构建 - \\_\\_doBuild：构建模块结构，缓存模块需要使用的节点，初始化组合控件的配置参数\n* 显示 - \\_\\_onShow：将模块放置到指定的容器中，分配组合控件，添加相关事件，执行\\_\\_onRefresh的业务逻辑\n* 刷新 - \\_\\_onRefresh：根据外界输入的参数信息获取数据并展示（这里主要做数据处理）\n* 隐藏 - \\_\\_onHide：模块放至内存中，回收在\\_\\_onShow中分配的组合控件和添加的事件，回收\\_\\_onRefresh中产生的视图（这里尽量保证执行完成后恢复到\\_\\_doBuild后的状态）\n\n具体模块实现举例\n\n```javascript\n/*\n * ------------------------------------------\n * 项目模块实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/klass',\n    'util/dispatcher/module',\n    '/path/to/project/module.js'\n],function(_k,_e,_t,_p){\n    // variable declaration\n    var _pro;\n    /**\n     * 项目模块对象\n     * @class   {_$$ModuleDemo}\n     * @extends {_$$Module}\n     * @param   {Object} 可选配置参数\n     */\n    _p._$$ModuleDemo = _k._$klass();\n    _pro = _p._$$ModuleDemo._$extend(_t._$$Module);\n    /**\n     * 构建模块，主要处理以下业务逻辑\n     * - 构建模块结构\n     * - 缓存后续需要使用的节点\n     * - 初始化需要使用的组件的配置信息\n     * @return {Void}\n     */\n    _pro.__doBuild = function(){\n        this.__super();\n        // TODO\n    };\n    /**\n     * 显示模块，主要处理以下业务逻辑\n     * - 添加事件\n     * - 分配组件\n     * - 处理输入信息\n     * @param  {Object} 输入参数\n     * @return {Void}\n     */\n    _pro.__onShow = function(_options){\n        this.__super(_options);\n        // TODO\n    };\n    /**\n     * 刷新模块，主要处理以下业务逻辑\n     * - 分配组件，分配之前需验证\n     * - 处理输入信息\n     * - 同步状态\n     * - 载入数据\n     * @return {Void}\n     */\n    _pro.__onRefresh = function(_options){\n        this.__super(_options);\n        // TODO\n    };\n    /**\n     * 隐藏模块，主要处理以下业务逻辑\n     * - 回收事件\n     * - 回收组件\n     * - 尽量保证恢复到构建时的状态\n     * @return {Void}\n     */\n    _pro.__onHide = function(){\n        this.__super();\n        // TODO\n    };\n    // notify dispatcher\n    _e._$regist(\n        'umi_or_alias',\n        _p._$$ModuleDemo\n    );\n\n    return _p;\n});\n```\n#### 消息\n\n##### 点对点消息\n\n模块可以通过\\_\\_doSendMessage接口向指定UMI的模块发送消息，也可以通过实现\\_\\_onMessage接口来接收其他模块发给他的消息\n\n发送消息\n\n```javascript\n_pro.__doSomething = function(){\n\n    // TODO\n\n    this.__doSendMessage(\n        '/m/setting/account/',{\n            a:'aaaaaa',\n            b:'bbbbbbbbb'\n        }\n    );\n};\n```\n\n接收消息\n\n```javascript\n_pro.__onMessage = function(_event){\n    // _event.from 消息来源\n    // _event.data 消息数据，这里可能是 {a:'aaaaaa',b:'bbbbbbbbb'}\n\n    // TODO\n};\n```\n\n##### 发布订阅消息\n\n发布消息\n\n```javascript\n_pro.__doSomething = function(){\n\n    // TODO\n\n    this.__doPublishMessage(\n        'onok',{\n            a:'aaaaaa',\n            b:'bbbbbbbb'\n        }\n    );\n};\n```\n\n订阅消息\n\n```javascript\n_pro.__doBuild = function(){\n\n    // TODO\n\n    this.__doSubscribeMessage(\n        '/m/message/account/','onok',\n        this.__onMessageReceive._$bind(this)\n    );\n};\n```\n\n#### 自测\n\n创建html页面，使用模板引入模块实现文件\n\n```html\n<!-- template box -->\n<div id=\"template-box\" style=\"display:none;\">\n  <textarea name=\"html\" data-src=\"../index.html\"></textarea>\n</div>\n```\n\n模块放至document.mbody指定的容器中\n\n```javascript\nNEJ.define([\n    'util/dispatcher/test'\n],function(_e){\n    document.mbody = 'module-id-0';\n    // test module\n    _e._$testByTemplate('template-box');\n});\n```\n\n### 系统整合\n\n#### 映射依赖关系树\n\n系统整合时，我们只需要将依赖关系树中需要注册模块的节点同模块实现文件进行映射即可\n\n对外模块整合\n\n![对外模块整合](http://img2.ph.126.net/CQe6y5Bdgkl4bA5VsSIwzA==/6608893914701623469.png)\n\n私有模块整合\n\n![私有模块整合](http://img0.ph.126.net/upKrOu1fEmK_Q6x2jc-ibA==/6619430534630239416.png)\n\n#### 提取系统配置信息\n\n规则配置举例\n\n```javascript\n  rules:{\n      rewrite:{\n          '404':'/m/blog/list/',\n          '/m/blog/list/':'/m/blog/',\n          '/m/setting/account/':'/m/setting/'\n      },\n      title:{\n          '/m/blog/tag/':'日志标签',\n          '/m/blog/list/':'日志列表',\n          '/m/setting/permission/':'权限管理',\n          '/m/setting/account/':'基本资料',\n          '/m/setting/account/edu/':'教育经历'\n      },\n      alias:{\n          'system-tab':'/?/tab/',\n          'blog-tab':'/?/blog/tab/',\n          'blog-list-box':'/?/blog/box/',\n          'blog-list-tag':'/?/blog/tag/',\n          'blog-list-class':'/?/blog/class/',\n          'blog-list':'/?/blog/list/',\n          'setting-tab':'/?/setting/tab/',\n          'setting-account-tab':'/?/setting/account/tab/',\n\n          'layout-system':'/m',\n          'layout-blog':'/m/blog',\n          'layout-blog-list':'/m/blog/list/',\n          'layout-setting':'/m/setting',\n          'layout-setting-account':'/m/setting/account',\n\n          'blog-tag':'/m/blog/tag/',\n          'setting-edu':'/m/setting/account/edu/',\n          'setting-profile':'/m/setting/account/',\n          'setting-permission':'/m/setting/permission/'\n      }\n  }\n```\n\n模块配置举例\n\n```javascript\n  modules:{\n      '/?/tab/':'module/tab/index.html',\n      '/?/blog/tab/':'module/blog/tab/index.html',\n      '/?/blog/box/':'module/blog/list.box/index.html',\n      '/?/blog/tag/':'module/blog/list.tag/index.html',\n      '/?/blog/class/':'module/blog/list.class/index.html',\n      '/?/blog/list/':'module/blog/list/index.html',\n      '/?/setting/tab/':'module/setting/tab/index.html',\n      '/?/setting/account/tab/':'module/setting/account.tab/index.html',\n\n      '/m':{\n          module:'module/layout/system/index.html',\n          composite:{\n              tab:'/?/tab/'\n          }\n      },\n      '/m/blog':{\n          module:'module/layout/blog/index.html',\n          composite:{\n              tab:'/?/blog/tab/'\n          }\n      },\n      '/m/blog/list/':{\n          module:'module/layout/blog.list/index.html',\n          composite:{\n              box:'/?/blog/box/',\n              tag:'/?/blog/tag/',\n              list:'/?/blog/list/',\n              clazz:'/?/blog/class/'\n          }\n      },\n      '/m/blog/tag/':'module/blog/tag/index.html',\n\n      '/m/setting':{\n          module:'module/layout/setting/index.html',\n          composite:{\n              tab:'/?/setting/tab/'\n          }\n      },\n      '/m/setting/account':{\n          module:'module/layout/setting.account/index.html',\n          composite:{\n              tab:'/?/setting/account/tab/'\n          }\n      },\n      '/m/setting/account/':'module/setting/profile/index.html',\n      '/m/setting/account/edu/':'module/setting/edu/index.html',\n      '/m/setting/permission/':'module/setting/permission/index.html'\n  }\n```\n\n#### 模块组合\n\n模块通过\\_\\_export属性开放组合模块的容器，\\_\\_export中的parent为子模块的容器节点，顶层模块（如 “/m”）可以通过重写\\_\\_doParseParent来明确指定应用所在容器\n\n```javascript\n_pro.__doBuild = function(){\n    this.__body = _e._$html2node(\n        _e._$getTextTemplate('module-id-l2')\n    );\n    // 0 - box select\n    // 1 - class list box\n    // 2 - tag list box\n    // 3 - sub module box\n    var _list = _e._$getByClassName(this.__body,'j-flag');\n    this.__export = {\n        box:_list[0],\n        clazz:_list[1],\n        tag:_list[2],\n        list:_list[3],\n        parent:_list[3]\n    };\n};\n```\n\n通过composite配置模块组合\n\n```javascript\n'/m/blog/list/':{\n    module:'module/layout/blog.list/index.html',\n    composite:{\n        box:'/?/blog/box/',\n        tag:'/?/blog/tag/',\n        list:'/?/blog/list/',\n        clazz:'/?/blog/class/'\n    }\n}\n```\n\n模块组合时可以指定组合模块的处理状态\n* onshow  - 这里配置的组合模块仅在模块显示时组合，后续的模块refresh操作不会导致组合模块的refresh，适合于模块在显示后不会随外界输入变化而变化的模块\n* onrefresh  -  这里配置的模块在模块显示时组合，后续如果模块refresh时也会跟随做refresh操作，适用于组合的模块需要与外部输入同步的模块\n* 不指定onshow或者onrefresh的模块等价于onrefresh配置的模块\n\n```javascript\ncomposite:{\n    onshow:{\n        // 模块onshow时组合\n        // 组合的模块在模块onrefresh时不会刷新\n    },\n    onrefresh{\n        // 模块onshow时组合\n        // 组合的模块在模块onrefresh时也同时会刷新\n    }\n    // 这里配置的组合模块等价于onrefresh中配置的模块\n}\n```\n\n#### 启动应用\n\n根据配置启动应用\n\n```javascript\nNEJ.define([\n    'util/dispatcher/dispatcher'\n],function(_e){\n    _e._$startup({\n        // 规则配置\n        rules:{\n            rewrite:{\n                // 重写规则配置\n            },\n            title:{\n                // 标题配置\n            },\n            alias:{\n                // 别名配置\n                // 建议模块实现文件中的注册采用这里配置的别名\n            }\n        },\n        // 模块配置\n        modules:{\n            // 模块UMI对应实现文件的映射表\n            // 同时完成模块的组合\n        }\n    });\n});\n```\n\n### 打包发布\n\n打包发布内容详见[NEJ工具集](https://github.com/genify/toolkit)相关文档\n\n## 系统变更\n\n当系统需求变化而进行模块变更我们只需要开发新的模块或删除模块配置即可\n\n### 新增模块\n\n如果新增的模块功能在系统中已经实现，则只需修改配置即可，如上例中我们需要在将日志管理下的标签模块在博客设置中也加一份，访问路径为/m/setting/tag/\n\n![新增模块](http://img0.ph.126.net/s4pv6FZmPal8Jx0m0eNltA==/6619471216560468933.png)\n\n修改规则配置\n\n```javascript\nrules:{\n    // ...\n    alias:{\n        // ...\n        'blog-tag':['/m/blog/tag/','/m/setting/tag/']\n    }\n}\n```\n\n修改模块配置\n\n```javascript\nmodules:{\n    // ...\n    '/m/setting/tag/':'module/blog/tag/index.html'\n}\n```\n\n如果要在/?/setting/tab模块的结构模板中增加一个标签即可\n\n```html\n<textarea name=\"txt\" id=\"module-id-8\">\n  <div class=\"ma-t w-tab f-cb\">\n    <a class=\"itm fl\" href=\"#/setting/account/\" data-id=\"/setting/account/\">账号管理</a>\n    <a class=\"itm fl\" href=\"#/setting/permission/\" data-id=\"/setting/permission/\">权限设置</a>\n    <a class=\"itm fl\" href=\"#/setting/tag/\" data-id=\"/setting/tag/\">日志标签</a>\n  </div>\n</textarea>\n```\n\n### 删除模块\n\n将退化的模块从系统中删除只需要将模块对应的UMI配置从模块配置中删除即可，而无需修改具体业务逻辑\n\n\n\n"
  },
  {
    "path": "doc/FAQ.md",
    "content": ""
  },
  {
    "path": "doc/MESSAGE.md",
    "content": "# 跨域窗体消息系统\n\n## 概述\n\n由于同源策略的限制，非同域的窗体之间不能直接进行数据通讯或共享，因此我们引入这部分内容来分析解决非同域及同域的窗体之间的数据通讯或共享问题。\n\n这里的消息通讯是指应用在客户端跨窗体之间的消息交互，可以保证在不会被恶意攻击的前提下进行跨窗体的数据共享方式，这里不会涉及到客户端与服务器端的信息交互。\n\n关于这部分对应的W3C规范的详细介绍可参阅[HTML5 Web Message](http://www.w3.org/TR/webmessaging/)\n\n## 实现分析\n\n消息通讯主要包含两个过程：\n\n* 收消息：文档通过监听当前窗体的onmessage事件来接收来自其他窗体的消息\n* 发消息：文档可以通过给定的接口向指定的窗体发送消息，包括跨域的窗体\n\n原理示意图如下所示\n\n![web message原理](http://img1.ph.126.net/YJDCgyyYN9oEYj6M6nd4Wg==/6608228710167581530.png)\n\n这里我们可以简单理解为各个窗体之间有一个消息通道，对于消息通道的关系我们定义为以下两种类型：\n\n* 直接父子关系：消息通道所在的窗体为父子关系\n* 兄弟及祖孙关系：消息通道所在的窗体为兄弟关系，或者父窗体和子窗体的若干层子窗体关系\n\n对于全浏览器平台兼容的消息机制实现一般采用以下两种方式\n\n* HTML5 Web Message\n* window.name代理\n\n## HTML5 Web Message\n\n### 原理\n\n对于高版本实现了符合W3C [HTML5 Web Message](http://www.w3.org/TR/webmessaging/) 规范的浏览器，我们可以直接使用该规范提供的API来实现跨域的窗体之间的消息通信\n\n#### MessageEvent\n\nMessageEvent定义\n\n![message event](http://img2.ph.126.net/YAxyMByji3SBIkgz563_1g==/2209297092302616725.png)\n\ndata\n\n* 消息内容，支持多种格式\n* IE8-9只支持字符串\n\norigin\n\n* 消息来源，如http://a.b.com:8080\n* 从安全角度出发在收到消息时务必做来源验证\n\nsource\n\n* 消息来源的窗体\n* 回复消息，如event.source.postMessage\n\nports\n\n* 消息通道，见[Channel](#Channel)部分说明\n* 发送消息，如event.ports[0].postMessage\n* webkit(chrome)/presto(opera)/trident(IE10+)支持\n\n#### 发消息\n\n原理图示\n\n![send message](http://img2.ph.126.net/EKXmXzABYnLfQATvn-GbQA==/1396397359562519963.png)\n\n发送消息使用规范定义的window.postMessage接口，接口定义如下\n\n|      | 类型 | 描述 |\n| :--- | :--- | :--- |\n| 输入 | Variable | 发送的数据，可以是基本类型，也可以是File、Blob等对象，注IE8-9支持传递字符串格式的数据 |\n|      | String   | 目标可接收消息的源信息，如果目标的源不是该参数指定的源则忽略此消息，如果所有源均可接收消息则可以传“*”，如果只允许同域的窗体接收消息则可以传“/” |\n|      | Array    | 可选，消息通道对象列表，主要用来代理非直接父子关系的窗体之间的消息通讯 |\n| 输出 | Void     | 无 |\n\n代码举例\n\n```html\n<iframe src=\"http://a.b.com:1144/frame-a.html\" name=\"A\"></iframe>\n```\n\n```javascript\n// 向名称为A的iframe发送消息，消息内容为字符串 connect\nwindow.frames.A.postMessage(\n    'connect',\n    'http://a.b.com:1144'\n);\n```\n\n#### 收消息\n\n接收消息使用规范定义的window.onmessage事件，接收到的事件对象见[MessageEvent](#MessageEvent)定义\n\n代码举例\n\n```javascript\n// http://a.b.com:1144/frame-a.html可以通过window.onmessage事件来监听其他窗口发过来的消息\nwindow.addEventListener(\n    'message',function(event){\n        // check origin\n        if (!isAllowed(event.origin))\n            return;\n        // check data format\n        if (!isFormatOK(event.data))\n            return;\n        // TODO something\n        ...\n        // reply to source\n        event.source.postMessage('message',event.origin);\n    },false\n);\n```\n\n#### Channel\n\n前面我们通过postMessage接口和onmessage事件实现了父子窗体之间的消息通讯，接下来我们需要完成兄弟关系的窗体之间的消息通讯\n\n![message between sibling](http://img2.ph.126.net/-eHlgNW2xZrps3HETzHvjQ==/1414411758071900501.png)\n\n这里如果window2要向window1发送消息，因为window2不能直接拿到window1的窗体对象，因此无法直接通过postMessage接口来向window1发送消息，一种折中的方式就是通过父窗体将消息做一次转发，window2先给消息parent，然后由parent将消息转交给window1，如下图所示\n\n![message by parent proxy](http://img1.ph.126.net/Xjfu7BcqwtGbhkbbUDMFMA==/6619527291653512726.png)\n\n但是这样我们会发现消息的路径比较长，因此效率比较低，W3C针对此类消息提供了MessageChannel机制来完成消息通讯\n\n一个MessageChannel包含两个端口，每个端口可以独立的完成消息的收发功能\n\n![message channel abstract](http://img2.ph.126.net/kv-J9xwXLKRUYweaUKkqDw==/2210985942163057055.png)\n\nMessageChannel定义\n\n![message channel](http://img2.ph.126.net/MV9A26usRaaTBOT7keKDVw==/4796333603250057446.png)\n\n因此兄弟关系的窗体之间的消息通讯机制可抽象为如下图所示\n\n![message between sibling](http://img2.ph.126.net/jjYkSurWb66RN3ALMVktOQ==/3017974700392032857.png)\n\n下面通过代码例子来解析整个流程\n\n假设一个页面有两个跨域的iframe窗体，需要实现通过MessageChannel从A窗体向B窗体发送消息的功能\n\n```html\n<iframe src=\"http://a.b.com:1144/frame-a.html\" name=\"A\"></iframe>\n<iframe src=\"http://d.e.com:1122/frame-b.html\" name=\"B\"></iframe>\n```\n\nA窗体中，我们需要先构建一个MessageChannel，在当前窗体上保持port1端口，通过port1端口进行消息的收发功能，然后将port2端口传递给parent窗体，由parent窗体将port2端口转交给B窗体\n\n```javascript\nvar channel = new MessageChannel();\nchannel.port1.onmessage = function(event){\n    // check origin from frame-b.html\n    if (event.origin!='http://d.e.com:1122')\n        return;\n    log('receive message from d.e.com and say: '+event.data);\n    // reply message\n    channel.port1.postMessage('hello B!',event.origin);\n};\n// build connect by parent\nparent.postMessage('connect','http://c.d.com:1100',[channel.port2]);\n```\n\nparent窗体需要将A窗口传过来的端口转交给B窗体，因此在parent窗体上需要做以下转发功能\n\n```javascript\nwindow.addEventListener(\n    'message',function(event){\n        // from frame-a to build connect\n        if (event.origin!='http://a.b.com:1144')\n            return;\n        // proxy port to frame-b\n        if (event.ports.length>0){\n            window.frames.B.postMessage(\n                'connect',\n                'http://d.e.com:1122',\n                [event.ports[0]]\n            );\n        }\n    },false\n);\n```\n\nB窗体在接收到parent传过来的port2端口后，保持port2端口，通过port2端口完成跟A窗体的消息收发功能\n\n```javascript\nwindow.addEventListener(\n    'message',function(event){\n        // check build channel message from parent\n        if (event.origin!='http://c.d.com:1100')\n            return;\n        // build channel\n        if (event.ports.length>0){\n            event.ports[0].onmessage = function(ev){\n                // check message from frame-a.html\n                if (ev.origin!='http://a.b.com:1144')\n                    return;\n                log('receive message from a.b.com and say: '+ev.data);\n            };\n            // send message to frame-a.html\n            event.ports[0].postMessage('hello A!',ev.origin);\n        }\n    },false\n);\n```\n\n至此A窗体和B窗体之间就建立了一条直接的MessageChannel，后续所有消息通过通过该消息通道直接进行通讯，而不需要通过parent做消息中转\n\n## window.name代理\n\n对于低版本浏览器主要针对Trident引擎的浏览器，如IE6-7版本，对于这类浏览器本身对Web Message规范的实现不完善，因此采用window.name作为代理来实现消息的传递。\n\n### 原理\n\n这里我们主要利用Trident引擎下跨域窗体可设置window.name的特性来实现消息的传递，具体实现原理示意图如下所示\n\n![message by window.name](http://img1.ph.126.net/NM6uHYXVUEU06McBcIR8tw==/6608700400654849159.png)\n\n假设上图Window1需要传递消息至Window2中，则消息的传递步骤如下：\n\n1.  Window1的消息发送器按照指定协议拼装消息\n2.  Window1的消息发送器将拼装好的消息字符串设置到Window2的window.name属性上\n3.  Window2起定时器轮询window.name的变化情况\n4.  Window2发现window.name中Window1设置的消息串，按照指定协议解码\n5.  Window2触发window上的onmessage事件通知上层应用收到消息\n\n反之亦然\n\n### 协议\n\n这里的协议主要指window.name上设置的消息串的格式\n\n* 必须以字符串 MSG| 作为起始，且必须大写字符\n* 参数以键值对方式传入，键与值之间用 = 连接，所有键值均做encodeURIComponent编码，键值对之间以 | 字符分隔，如 a=b|b=a%26b\n* 将以上结果做escape后设置到目标window的name属性上，如MSG%7Cdata%3D%257B%2522url%2522%253A%2522http%253A%252F%252Fa.b.com\n\n传递的参数信息主要包括\n\n| 参数名称 | 参数描述 |\n| :---     | :---     |\n| origin   | 目标接收消息的源信息 |\n| data     | 传递的消息数据，序列化为JSON字符串 |\n| ref      | 当前窗体的访问地址 |\n| self     | 当前窗体名称，默认为_parent |\n\n### 缺陷\n\n由于浏览器的限制本解决方案会存在以下一些问题\n\n1.  可能会有消息丢失\n\n    由于使用的是定时器轮询window.name的变化，而window.name为所有其他窗体共享的资源，但是其他窗体仅有设置权限而没有读取权限，因此无法保证window.name的消息在读取前被程序中其他代码覆盖，如果出现这种情况之前的消息无法到达当前窗体中。\n\n2.  没能真正意义上保证origin的限制条件\n\n    由于无法读取一个窗体的location信息，因此对origin的验证是在接收到消息后由框架额外做的封装，因此从真正意义上来说这个消息还是已经到达了当前窗体中，因此可能会存在信息的泄漏情况\n\n综上所述，对于低版本浏览器建议尽量避免传递一些敏感信息，同时系统也尽量避免强依赖消息传递机制来实现系统的重要功能。\n\n## NEJ封装\n\n[NEJ](https://github.com/NetEaseWD/NEJ) Web前端开发框架根据以上原理对消息通讯这部分做了封装，为上层应用提供统一的API，主要实现模块为 util/ajax/message\n\n### 发送消息\n\nNEJ封装的发送消息接口为_$postMessage，接口说明如下\n\n|      | 类型 |   描述 |\n| :--- | :--- | :--- |\n| 输入 | String/Window | 目标window对象或者Frame的name，或者字符串如\\_top、\\_parent、\\_self |\n|      | Object        | 消息配置信息 |\n| 输出 | Void          | 无 |\n\n消息配置信息包括\n\n| 名称 | 类型 | 描述 |\n| :--- | :--- | :--- |\n| data   | Variable  | 消息内容 |\n| origin | String    | 目标Origin，只有指定的页面可以收到消息，默认为所有源可接收，如http://a.b.com |\n| source | String    | 当前窗体标识，除非你非常确定当前窗体的标识是什么，否则请采用自动识别 |\n\n代码举例\n\n```html\n<!-- 注意需要通过source进行双向交互的frame节点必须设置id属性作为标识 -->\n<iframe id=\"targetFrame\" src=\"http://a.b.com/a.html\"></iframe>\n```\n\n```javacript\nNEJ.define([\n    'util/ajax/message'\n],function(_j){\n    // top页面代码\n    // 发送消息至 http://c.d.com 的页面\n    _j._$postMessage('targetFrame',{\n        data:'hello c.d.com',\n        origin:'http://c.d.com'\n    });\n\n    // 发送消息至 http://a.b.com 的页面\n    _j._$postMessage('targetFrame',{\n        data:'hello a.b.com'\n    });\n});\n```\n\n### 接收消息\n\n跟W3C规范一致，NEJ同样提供window.onmessage事件来接收消息，注这里的onmessage事件必须通过_$addEvent接口添加，接收到的消息格式遵循W3C中对于[MessageEvent](#MessageEvent)的规范\n\n代码举例\n\n```javacript\nNEJ.define([\n    'base/event'\n    'util/ajax/message'\n],function(_v,_j){\n    // 添加消息监测事件\n    _v._$addEvent(\n        window,'message',function(_event){\n            // 必须先验证消息来源_event.origin是否你允许的域\n             if (!_isAllow(_event.origin))\n                return;\n\n            // 处理_event.data中的消息内容\n            // TODO something\n\n            // 回复消息，使用_event.source\n            _j._$postMessage(_event.source,{\n                data:'hello!',\n                origin:_event.origin\n            });\n        }\n    );\n});\n```\n\n"
  },
  {
    "path": "doc/PLATFORM.md",
    "content": "# 平台适配系统\n\n## 概述\n\n随着WEB技术的发展，越来越多的平台开始使用WEB技术来构建系统，NEJ框架做为一套跨平台的技术解决方案框架集成了基于AOP思想的平台适配策略，该策略具有以下特性：\n\n* 屏蔽平台差异\n* 松耦合性（通过配置应用可以灵活的增删平台支持）\n* 可扩展性（框架可以快速增加对新平台的支持）\n* 可维护性（直接针对平台进行维护）\n* 工具支持（通过NEJ提供的打包工具可按需定制平台输出）\n\n## 平台分类\n\nNEJ框架根据WEB应用所在容器的差异将平台分为浏览器平台和混合应用平台两大类，各分类的详细说明见下文所述\n\n### 浏览器平台\n\n#### 按引擎划分\n\n浏览器平台按照主流引擎可以划分为以下几类：\n\n![按引擎划分平台](http://img0.ph.126.net/gmJEDK7pAdfE8nH4VQexkA==/6608273790144412074.png)\n\n| 引擎 | 说明 |\n| :--- | :--- |\n| Trident | 由微软研发的排版引擎，代表浏览器有Internet Explorer |\n| Webkit  | 由Apple、Google、Adobe等公司推动的开源的排版引擎，代表浏览器有Apple Safari、Google Chrome |\n| Gecko   | 由Mozilla基金会支持的开源排版引擎，代表浏览器有Mozilla Firefox |\n| Presto  | 由Opera Software研发的商用排版引擎，代表浏览器有Opera，由于Opera从15以后就开始采用新的Blink引擎，因此Presto也将逐步淡出我们的目标平台对象 |\n| Blink   | 由Google和Opera Software基于Webkit引擎研发的排版引擎，代表浏览器有Chrome 28+、Opera 15+ |\n\n根据对引擎分析及各引擎的流行度我们将默认目标平台锁定为Trident、Webkit、Gecko三大平台，根据平台适配策略我们后续可以快速的进行平台扩展，各引擎对应的平台依赖配置信息参阅《[NEJ依赖管理系统](./DEPENDENCY.md)》\n\n| 引擎    | 依赖配置参数p值 |\n| :---    | :--- |\n| Trident | td |\n| Webkit  | wk |\n| Gecko   | gk |\n\n#### 按功能划分\n\n各引擎的浏览器版本根据对标准、规范的支持程度进行划分可分为以下几类：\n\n![按功能划分平台](http://img1.ph.126.net/PELRvZvw_Gx7DTN3v7hUFQ==/6608921402492080696.png)\n\n由于目前国内基于Trident的Internet Explorer浏览器还占有大量的市场份额，包括低版本的Internet Explorer浏览器，因此我们将浏览器分成三个等级\n\n| 标准性 | 说明 |\n| :--- | :--- |\n| 差 | 主要针对低版本的Trident引擎（如IE6浏览器）平台，这部分平台对规范和标准的支持程度比较差，在适配时需要做大量额外的hack工作来实现相应的功能，因此如果产品的目标平台定位需要支持此平台则会有一定的性能损耗 |\n| 中 | 主要针对中间版本的Trident引擎（如IE7-9浏览器）平台，这部分平台对规范和标准有一定的支持，但是也存在若干功能需要做额外的hack工作来实现 |\n| 好 | 主要针对对规范、标准支持比较好的平台，按照标准实现的功能无需做额外的hack工作，因此如果产品的目标平台定位为此平台将取得比较好的用户体验和性能，如移动产品、混合应用等 |\n\n因此根据对引擎和浏览器份额的分析，NEJ针对Trident引擎默认支持导出的目标平台可分为三个等级，这里涉及的依赖管理相关信息参阅《[NEJ依赖管理系统](./DEPENDENCY.md)》\n\n| 等级 | 依赖配置参数p值 | 说明 |\n| :--- | :--- | :--- |\n| 差 |   td |    支持IE6的全平台等级 |\n| 中 |   td-0 |  支持>=IE7的等级 |\n| 好 |   td-1 |  支持IE10+的等级 |\n\n### 混合应用平台\n\n根据混合应用的宿主平台的差异我们将混合应用的目标平台分为以下几类：\n\n![混合平台划分](http://img1.ph.126.net/1VV98yGBpj3E2KPaa9M3jg==/6608853232771155778.png)\n\n| 宿主     | 说明 |\n| :---     | :--- |\n| Android  | Android系统的混合应用，浏览器引擎会自动适配至Webkit |\n| IOS      | IOS系统的混合应用，浏览器引擎会自动适配至Webkit |\n| WinPhone | Windows Phone系统的混合应用，浏览器引擎会自动适配至Trident |\n| PC       | 桌面应用，采用CEF做为容器，浏览器引擎会自动适配至Webkit |\n\nNEJ对于混合应用的配置提供以上四种平台的支持，这里涉及的依赖管理相关信息参阅《[NEJ依赖管理系统](./DEPENDENCY.md)》\n\n| 平台     | 依赖配置参数p值 |\n| :---     | :--- |\n| Android  | android |\n| IOS      | ios |\n| WinPhone | win |\n| PC-CEF   | cef |\n\n## 平台配置\n\n### 配置类型\n\n平台配置信息分两类基本配置：补丁配置和混合配置，因为混合模式下使用的浏览器引擎固定，因此当配置中出现混合类型的配置时忽略补丁配置的值。\n\n如果在引入依赖定义库时未指定平台信息则表示系统需对全平台浏览器支持。\n\n#### 补丁配置\n\n主要用来修正浏览器平台对接口及控件的支持，按照目前浏览器引擎划分，参数值由一个或者多个平台标识组成，多个平台用“|”分隔，标识支持如下所示：\n\n| 标识 | 说明 |\n| :--- | :--- |\n| gk   | 以gecko为核心的浏览器平台，如firefox等 |\n| wk   | 以webkit为核心的浏览器平台，如chrome、safari等 |\n| td   | 以trident为核心的浏览器平台，如IE、360、maxthon等 |\n| td-0 | 以trident为核心的浏览器平台，且引擎内核版本大于等于3.0，即IE>=7 |\n| td-1 | 以trident为核心的浏览器平台，且引擎内核版本大于等于7.0，即IE>=10 |\n\n![补丁配置举例](http://img2.ph.126.net/0Lice657qJuv-bQ5EMTjBA==/6608225411632792322.png)\n\n#### 混合配置\n\n主要用于混合开发模式下对native接口的适配，按照native平台划分，参数值由一个标识组成，多个标识则以识别的第一个标识为准，标识支持如下所示：\n\n| 标识    | 说明 |\n| :---    | :--- |\n| cef     | 基于cef框架混合应用，主要针对桌面应用 |\n| ios     | ios平台混合应用，如iphone应用、ipod应用、ipad应用等 |\n| win     | windows phone平台混合应用 |\n| android | android平台混合应用 |\n\n对于此类值的配置自动生成的native值为{lib}native/目录下的具体配置目录。\n\n![混合配置举例](http://img1.ph.126.net/QZTOhRvFyNtocnXu0jHdsQ==/6608507986120036696.png)\n\n### 配置方式\n\n平台参数在开发及打包过程中都会使用，NEJ框架支持平台参数的配置通过define.js路径上查询串中的p参数输入，同时也支持在打包工具配置文件中配置。\n\n#### 查询参数配置\n\n通过引入的define.js路径上的p查询参数配置，可以按照浏览器引擎配置\n\n```html\n<script src=\"/lib/define.js?p=wk|gk|td\"></script>\n```\n\n也可以按照混合应用的宿主平台进行配置\n\n```html\n<script src=\"/lib/define.js?p=android\"></script>\n```\n\n#### 打包参数配置\n\n除了通过查询配置参数进行平台配置外还可以使用打包参数进行平台配置，打包时打包参数的配置优先级大于查询参数，对于非NEJ文件依赖管理的系统因为没有引入define.js，所以只能采用打包参数配置的形式\n\n```\n # NEJ平台适配参数，等价于define.js?p=wk|td这里p的配置\n # 优先级比p参数高，配置规则同p\n NEJ_PLATFORM = wk|td\n```\n\n## 实现机制\n\n### 平台分离策略\n\n#### AOP思想\n\nAOP(Aspect-Oriented Programming)：面向切面的编程范式，其核心思想是将横切关注点从主关注点中分离出来，因此特定领域的问题代码可以从标准业务逻辑中分离出来，从而使得主业务逻辑和领域性业务逻辑之间不会存在任何耦合性。\n\nNEJ框架利用AOP思想来实现平台的适配策略，结合不同的平台实现逻辑，我们可以认为对于使用规范、标准来实现业务逻辑的部分为我们的主关注点，而不同平台可以做为若干的切面关注点进行封装，各平台只需关注自己平台下对标准的修正逻辑即可，因此可以通过增加删平台修正逻辑来实现对不同平台的适配。\n\n实现时我们首先提取标准业务逻辑，然后各平台根据实际情况实现对业务逻辑的修正\n\n![AOP策略](http://img2.ph.126.net/27YJvuHJvtvBFv4FoYX7QA==/6608822446445580374.png)\n\n* 标准业务逻辑：主关注点，这里主要是使用根据W3C、ES标准来实现的业务逻辑\n* 前置平台修正逻辑：领域特定关注点，主要是根据平台特性对标准在该平台下的修正，修正逻辑会先于标准逻辑执行\n* 后置平台修正逻辑：同前置平台修正逻辑，也是领域特定关注点，修正逻辑会在标准逻辑执行后再执行\n\n根据此思路我们对比以下两段代码：\n\n代码一：目前常用的平台检查方式\n\n```javascript\nfunction doSomething(){\n    if(isTrident){\n        // TODO trident implement\n    }else if(isWebkit){\n        // TODO webkit implement\n    }else if(isGecko){\n        // TODO gecko implement\n    }else if(isPresto){\n        // TODO presto implement\n    }else{\n        // TODO w3c implement\n    }\n}\n```\n\n此方式对所有平台的修正逻辑均在主逻辑中实现，存在以下弊端：\n\n* 对平台特有的修正逻辑耦合在主逻辑中，平台特有的更新必然引起主逻辑的更新\n* 对于新增或删除平台的支持必须修改到主业务逻辑\n* 无法分离不必要的平台修正，比如基于webkit引擎的移动平台应用\n\n代码二：NEJ框架的平台适配方式\n\n```javascript\nfunction doSomething(){\n    // TODO w3c implement\n}\n\n// trident implement\ndoSomething = doSomething._$aop(\n    function(_event){\n        // TODO trident implement\n    }\n);\n// … …\n\ndoSomething(1,2,3);\n```\n\n对比代码一，我们可以发现NEJ框架中的接口适配方式分离了标准业务逻辑和平台特有业务逻辑，而是否增加平台特有业务逻辑并不会影响主业务逻辑的执行，因此我们可以从中得到以下好处：\n\n* 主逻辑和平台特有逻辑无耦合性，可随意分离、合并\n* 对于新增平台适配只需新加平台特有逻辑即可，而无需影响到主业务逻辑\n* 可通过配置有选择性的导出平台特有业务逻辑\n\n#### _$aop\n\nNEJ框架在Function的原型链上增加了\\_$aop接口的支持来做平台适配\n\n|      | 类型 |   描述 |\n| :--- | :--- | :--- |\n| 输入 | Function |   平台前置业务逻辑 |\n|      | Function | 平台后置业务逻辑 |\n| 输出 | Function |   封装了平台前置、后置业务逻辑的执行函数 |\n| 描述 |          | AOP适配逻辑封装整合 |\n\n对于平台前置、后置业务逻辑的执行函数接受一个输入参数，该参数包含以下信息\n\n| 参数名称 | 类型     | 描述 |\n| :---     | :---     | :--- |\n| args     | Array    | 输入参数列表，调整参数值将影响后续阶段的输入 |\n| value    | Variable | 返回值，后续阶段可取到此值 |\n| stopped  | Boolean  | 是否继续执行后续阶段的业务逻辑 |\n\n代码举例：\n\n平台差异API的提取\n\n```javascript\nfunction doSomething(a,b,c){\n    // TODO do something\n};\n\ndoSomething(1,2,3);\n```\n\n平台适配逻辑\n\n```javascript\ndoSomething = doSomething._$aop(\n    function(_event){\n        // _event.args -> [a,b,c]\n        // _event.stopped = true;\n        // _event.value = 'aaaaaaa';\n\n        // TODO before doSomething\n    },\n    function(_event){\n        // _event.args -> [a,b,c]\n        // _event.value = 'bbbbbb';\n\n        // TODO after doSomething\n    }\n);\n\ndoSomething(1,2,3);\n```\n\n### 按需适配策略\n\n前面NEJ提供了将平台适配的主业务逻辑和平台业务逻辑的分离机制，除此之外还需要提供一种机制能够让平台按需适配，并能通过平台配置的形式按需导出\n\n#### platform\n\n控件依赖补丁名称为“platform”，只用于文件依赖，使用“{platform}xxx.js”来表示控件依赖的补丁文件，会解析为依赖xxx.js和xxx.patch.js两个文件。xxx.js为W3C/ES规范实现方式，提供所有标准平台支持的公用部分，xxx.patch.js通过NEJ.patch接口提供不同平台对这些接口的特有实现逻辑\n\n一个典型的适配控件结构如下图所示\n\n![适配控件结构](http://img1.ph.126.net/shaaEm3oj13JZcdMF9iHTQ==/6608208918958379461.png)\n\n这里的widget.js是控件业务逻辑实现文件，在此控件的实现中会依赖到存在平台差异的API，其依赖代码如下所示\n\n```javascript\nNEJ.define([\n    'util/event',\n    '{platform}api.js'\n],function(t,h,p){\n\n    // TODO\n\n});\n```\n\n这里对 {platform}api.js 的处理方式如下图所示，这里的./相对于当前的代码文件即widget.js文件所在的目录\n\n![platform](http://img2.ph.126.net/ygcxx2DAXf5YbpQ8No7SWg==/6608689405538619068.png)\n\n这里的api.js文件为需平台适配API的标准实现逻辑，而api.patch.js文件则利用NEJ.patch接口对各平台做按需适配逻辑，同时打包时也根据NEJ.patch接口中对平台的条件识别做按需输出，由于api.patch.js文件最终会按需输出，因此在此文件中除了使用NEJ.patch做平台适配逻辑外不允许包括其它业务逻辑\n\n#### NEJ.patch\n\nNEJ框架中的平台按需适配采用NEJ.patch接口来实现，由于打包发布后NEJ.patch相关的接口会被分离出来不会发布上线，因此仅允许在patch文件中调用此接口，平台引擎标识说明如下\n\n| 标识  | 说明 |\n| :---  | :--- |\n| T     | Trident引擎，如IE |\n| W     | Webkit引擎，如chrome |\n| G     | Gecko引擎，如firefox |\n\n内置的Trident引擎版本对应的IE版本关系\n\n| Trident版本 | IE版本 |\n| :---  | :--- |\n| 2.0 | 6 |\n| 3.0 | 7 |\n| 4.0 | 8 |\n| 5.0 | 9 |\n| 6.0 | 10 |\n| 7.0 | 11 |\n\n接口说明\n\n|      | 类型 | 描述 |\n| :--- | :--- | :--- |\n| 输入 | String   |   必须，平台的判断条件，如2=<TR<4 |\n|      | Array    | 可选，依赖文件列表，规则同define接口定义的文件路径 |\n|      | Function | 可选，当前条件下需要执行的脚本 |\n| 输出 | Void     | 无 |\n\n```javascript\n\n// 此文件只能定义NEJ.patch不可执行其他业务逻辑\n// 打包输出时仅根据平台配置输出所需处理逻辑\n\nNEJ.define([\n    './hack.js'\n],function(h){\n    // 针对trident平台的处理逻辑\n    NEJ.patch('TR',function(){\n        // TODO\n    });\n    // 针对gecko平台的处理逻辑\n    NEJ.patch('GR',[\n        './hack.firefox.js'\n    ],function(fh){\n        // TODO\n    });\n    // 针对IE6平台的处理逻辑\n    NEJ.patch('TR==2.0',['./hack.ie6.js']);\n    // 针对IE7-IE9的处理逻辑\n    NEJ.patch('3.0<=TR<=5.0',function(){\n        // TODO\n    });\n\n    // 这里必须同hack.js文件的返回值一致\n    return h;\n});\n```\n\n## 平台变更\n\n当平台发生变更时我们可以快速进行扩充或缩减\n\n### 平台扩充\n\n当有新平台需要作为系统目标平台时，我们只需要做以下工作：\n\n* 增加平台配置识别符，如nxw\n* 识别该平台与标准存在的差异，增加平台特有业务逻辑至patch\n* 系统对平台配置部分增加新添的识别符，如\n\n    原平台适配\n    ```html\n    <script src=\"/path/to/nej/define.js?p=wk|gk|td\"></script>\n    ```\n    新增平台适配\n    ```html\n    <script src=\"/path/to/nej/define.js?p=wk|gk|td|nxw\"></script>\n    ```\n\n即可完成对平台的扩充，而不会影响到原有的业务逻辑\n\n### 平台缩减\n\n当系统适配的目标平台由于种种原因逐步退出历史舞台时，我们的系统也需要将该平台的冗余代码从系统中剔除，我们只需要做以下工作：\n\n* 系统对平台配置部分删除要剔除的平台标识，如\n\n    原平台适配\n    ```html\n    <script src=\"/path/to/nej/define.js?p=wk|gk|td\"></script>\n    ```\n    缩减后平台适配\n    ```html\n    <script src=\"/path/to/nej/define.js?p=wk\"></script>\n    ```\n\n即可完成对平台的缩减，而无需修改任何业务逻辑\n\n## 使用规范\n\n### 目录规范\n\n对于存在平台适配的API或者控件实现时需要将平台适配相关的代码放在platform目录下，适配相关文件包含两部分：标准逻辑实现文件和适配逻辑实现文件，其中适配逻辑实现文件命名必须为标准实现文件名加”.patch”做为后缀，如下图所示标准逻辑实现文件w1.js对应的平台适配逻辑实现文件名必须为w1.patch.js\n\n![目录规范](http://img0.ph.126.net/XDO5ArV_6or1s2vUQEiENw==/6608191326772334325.png)\n\n这里对于控件的实现文件路径和命名没有强制规定，因为{platform}相对于当前路径搜索适配文件，所以对于层级目录的控件实现文件中如果需要依赖平台文件则可以使用类似../../{platform}w1.js的形式引入\n\n### 编码规范\n\n编码规范这里主要针对patch文件有以下约束，其他遵循NEJ编码规范即可\n\n* patch文件只允许调用NEJ.patch接口做平台适配相关业务逻辑\n* patch文件必须显式的依赖标准逻辑实现文件\n* 不同平台依赖的外部文件在实现时必须处理好平台识别\n* patch文件返回结果必须同标准逻辑实现文件一致\n\n## 使用范例\n\n### 步骤一\n\n构建控件目录，可以使用[NEJ工具集](https://github.com/genify/toolkit)的nej-widget指令生成\n\n![控件目录](http://img2.ph.126.net/SSxNFLzX53Nb8r5DLuukQg==/6608848834724645147.png)\n\n### 步骤二\n\n实现控件主业务逻辑（widget.js），这里依赖适配文件hack.js\n\n```javascript\nNEJ.define([\n    '{platform}hack.js'\n],function(){\n    // TODO\n    console.log('widget ok');\n});\n```\n\n### 步骤三\n\n实现适配接口的标准业务逻辑（hack.js），这里依赖平台解析文件base/platform\n\n```javascript\nNEJ.define([\n    'base/platform'\n],function(_h){\n\n    // common api for w3c or es\n    _h.__doSomething = function(){\n        // TODO\n    };\n\n    console.log('from common hack file');\n});\n```\n\n### 步骤四\n\n实现适配业务逻辑（hack.patch.js），这里需要显式指定标准逻辑实现文件hack.js，对于不同平台复杂的适配实现可以采用外链依赖的方式实现\n\n```javascript\n// 此文件只能定义NEJ.patch不可执行其他业务逻辑\n// 打包输出时仅根据平台配置输出所需处理逻辑\nNEJ.define([\n    './hack.js'\n],function(_h){\n    // 针对trident平台的处理逻辑\n    NEJ.patch('TR',function(){\n        // TODO\n        console.log('from inline ie');\n    });\n\n    // 针对webkit平台的处理逻辑\n    NEJ.patch('WR',[\n        './hack.chrome.js'\n    ],function(_hc){\n        // TODO\n        console.log('from inline chrome');\n    });\n\n    // 针对gecko平台的处理逻辑\n    NEJ.patch('GR',[\n        './hack.firefox.js'\n    ],function(_hf){\n        // TODO\n        console.log('from inline firefox');\n    });\n\n    // 针对IE6平台的处理逻辑\n    NEJ.patch('TR==2.0',['./hack.ie6.js']);\n\n    // 针对IE7-IE9的处理逻辑\n    NEJ.patch('3.0<=TR<=5.0',function(){\n        // TODO\n        console.log('from inline ie7-ie9');\n    });\n\n    // 这里必须返回hack.js返回的结果\n    return _h;\n});\n```\n\n### 步骤五\n\n外链平台适配文件的实现（hack.ie6.js）\n\n```javascript\nNEJ.define([\n    'base/platform',\n    './hack.js'\n],function(_p,_h){\n\n    // 外链适配依赖做好平台识别\n    if (_p._$NOT_PATCH.trident0) return;\n\n    // patch for ie6\n    _h.__doSomething =\n    _h.__doSomething._$aop(\n        function(_event){\n            // TODO\n        }\n    );\n\n    console.log('from ie6 dep file');\n});\n```\n\n"
  },
  {
    "path": "doc/TEMPLATE.md",
    "content": "# 模板系统\n\n## 概述\n\n模板系统主要用来分离视图与数据，用以生成特定格式的文档，可以提升开发效率，良好的设计也可以使得代码重用变得更加容易，主要特点包括：\n\n* 分离代码（业务逻辑代码与视图代码）\n* 数据分离（动态数据与静态数据）\n* 代码单元共享（代码共享）\n\n本文主要介绍NEJ框架的模板系统及其使用，模板系统提供两大类模板的支持：基本类型和资源类型，模版系统的实现模块包括util/template/tpl和util/template/jst\n\n## 模板结构\n\nNEJ模板系统可以直接用字符串作为模板，也可以使用TEXTAREA标签封装模板，使用TEXTAREA标签封装模版的形式如下\n\n![模板类型](http://img2.ph.126.net/W_RhwYyx4kbPPGMpcVoUwQ==/6608414527633039667.png)\n\n### 基本类型\n\n结构范例\n\n```html\n<textarea name=\"txt\" id=\"txt-template-1\">\n  <div>\n    <p>aaaaaaaaaaaaaa</p>\n    <!-- content here -->\n  </div>\n</textarea>\n```\n\n#### name\n\n标识模板类型，主要包括txt/jst/ntp三种，每种类型的详细说明见模板类型章节\n\n#### id\n\n模板标识，后续可以用模板接口输入该ID取得模板的内容\n\n### 资源类型\n\n结构范例\n\n```html\n<textarea name=\"css\" data-src=\"./a.css\" data-version=\"20140901\">\n  .a{color:#000;}\n  .b{color:#ddd;}\n</textarea>\n```\n\n#### name\n\n标识模板类型，主要包括css/js/html/res四种类型\n\n#### data-src\n\n标识模板资源地址，多个地址用“,”分隔，以“./”，“../”开始的相对路径相对于当前文件所在的目录\n\n#### data-version\n\n资源版本信息\n\n## 模板类型\n\n模板系统提供两类模板，根据实际需求，每类模板又做了细化分类\n\n### 基本类型\n\n基本类型模板主要包括 txt/jst/ntp 三类模板\n\n#### txt\n\ntxt模板提供了基本的文本缓存功能, 模板标示符为txt，开发人员可以使用这个模板来缓存html结构\n\n如果脚本里已经有了模版内容则可以通过_$addTextTemplate接口添加到缓存中\n\n代码举例\n\n```javascript\nNEJ.define([\n    'util/template/tpl'\n],function(_t){\n    // 模版添加到缓存池中\n    _t._$addTextTemplate('txt-template-1','\\\n        <div>\\\n          <p>aaaaaaaaaaaaaa</p>\\\n          <!-- content here -->\\\n        </div>\\\n    ');\n\n    // TODO\n});\n```\n\n如果模版使用textarea标签封装的话采用以下形式\n\n代码举例\n\n```html\n<textarea name=\"txt\" id=\"txt-template-1\">\n  <div>\n    <p>aaaaaaaaaaaaaa</p>\n    <!-- content here -->\n  </div>\n</textarea>\n```\n\n此类模板后续可以使用_$getTextTemplate接口获取\n\n```javascript\nNEJ.define([\n    'util/template/tpl'\n],function(_t){\n    // 解析模版，支持textarea的批量解析\n    _t._$parseTemplate('txt-template-1');\n\n    // 根据模板ID取模板内容\n    // 返回字符串类型的模板内容\n    var _text = _t._$getTextTemplate('txt-template-1');\n\n    // TODO\n});\n```\n\n#### ntp\n\n节点模版，主要用于UI控件中对复杂结构的缓存和重用，见[ITEM控件](#ITEM控件)\n\n如果是字符串的模版，则可以通过_$addNodeTemplate接口添加至缓存\n\n代码举例\n\n```javascript\nNEJ.define([\n    'util/template/tpl'\n],function(_t){\n    // 模版添加到缓存池中\n    _t._$addNodeTemplate('ntp-template-1','\\\n        <div>\\\n          <p>aaaaaaaaaaaaaa</p>\\\n          <!-- content here -->\\\n        </div>\\\n    ');\n\n    // TODO\n});\n```\n\n如果模版使用textarea标签封装的话采用以下形式\n\n代码举例\n\n```html\n<textarea name=\"ntp\" id=\"ntp-template-1\">\n  <div>\n    <p>aaaaaaaaaaaaaa</p>\n    <!-- content here -->\n  </div>\n</textarea>\n```\n\n此类模板后续可以使用_$getNodeTemplate接口获取\n\n```javascript\nNEJ.define([\n    'util/template/tpl'\n],function(_t){\n    // 解析模版，支持textarea的批量解析\n    _t._$parseTemplate('ntp-template-1');\n\n    // 根据模板ID取模板内容\n    // 返回模板对应的DOM树结构\n    var _node = _t._$getNodeTemplate('ntp-template-1');\n\n    // TODO\n});\n```\n\n#### jst\n\n符合[JST语法](#JST语法)规则的模版，类似服务器端模版如freemarker、verlocity等\n\n如果模版是字符串，则可以通过_$add接口添加到缓存\n\n代码举例\n\n```javascript\nNEJ.define([\n    'util/template/jst'\n],function(_t){\n    // 添加JST模板缓存\n    _t._$add('\\\n        <table class=\"w-table\">\\\n          <thead>\\\n            <tr><th>序号</th><th>姓名</th><th>性别</th></tr>\\\n          </thead>\\\n          {if !defined(\"workers\")}\\\n          <tr><td colspan=\"3\">数据加载失败，请稍后再试！</td></tr>\\\n          {elseif workers&&workers.length}\\\n            {list workers as x}\\\n              <tr{if x_index==x_length-1} class=\"last\"{/if}>\\\n                <td>${x_index+1}</td>\\\n                <td>${x.name}</td>\\\n                <td>{if x.gender==1}男{else}女{/if}</td>\\\n              </tr>\\\n            {/list}\\\n          {else}\\\n          <tr><td colspan=\"3\">没有工人！</td></tr>\\\n          {/if}\\\n        </table>\\\n    ');\n})\n```\n\n如果模版使用textarea标签封装的话采用以下形式\n\n代码举例\n\n```html\n<textarea name=\"jst\" id=\"jst-template-1\">\n    <table class=\"w-table\">\n      <thead>\n        <tr><th>序号</th><th>姓名</th><th>性别</th></tr>\n      </thead>\\\n      {if !defined(\"workers\")}\n      <tr><td colspan=\"3\">数据加载失败，请稍后再试！</td></tr>\n      {elseif workers&&workers.length}\n        {list workers as x}\n          <tr{if x_index==x_length-1} class=\"last\"{/if}>\n            <td>${x_index+1}</td>\n            <td>${x.name}</td>\n            <td>{if x.gender==1}男{else}女{/if}</td>\n          </tr>\n        {/list}\n      {else}\n      <tr><td colspan=\"3\">没有工人！</td></tr>\n      {/if}\n    </table>\n</textarea>\n```\n\n后续可以使用_$get接口获取整合数据的结果\n\n代码举例\n\n```javascript\nNEJ.define([\n    'util/template/jst'\n],function(_t){\n    // 添加模版缓存\n    // 也可以用_$parseTemplate接口批量添加\n    _t._$add('jst-template-1');\n\n    // 根据模板ID取模板内容\n    // 返回整合数据后的html代码\n    var _html = _t._$get('jst-template-1',{\n        workers:[\n            {name:'abc',gender:1},\n            {name:'def',gender:1},\n            {name:'ghi'}\n        ]\n    });\n\n    // TODO\n});\n```\n\n### 资源类型\n\n资源类型模板又分为 css/js/html/res 四类，资源类模板只能用TEXTAREA标签封装\n\n#### css\n\n样式资源模版，可以采用内联也可以采用外联方式载入\n\n代码举例\n\n```html\n<div id=\"template-box\">\n    <!-- 纯内联样式 -->\n    <textarea name=\"css\">\n      .a{color:#aaa;}\n      .b{color:#bbb;}\n    </textarea>\n\n    <!-- 纯外联 -->\n    <textarea name=\"css\" data-src=\"./a.css,./b.css\" data-version=\"v1\"></textarea>\n\n    <!-- 复合内联外联 -->\n    <textarea name=\"css\" data-src=\"./a.css,./b.css\" data-version=\"v1\">\n      .a{color:#aaa;}\n      .b{color:#bbb;}\n    </textarea>\n</div>\n```\n\n对于内外联复合的样式模板，解析成样式时，内联的样式在外联的样式的后面\n\n系统初始化时使用_$parseTemplate接口解析模版\n\n代码举例\n\n```javascript\nNEJ.define([\n    'util/template/tpl'\n],function(_t){\n    // 激活样式模版\n    _t._$parseTemplate('template-box');\n\n    // TODO\n});\n```\n\n#### js\n\n脚本资源模版，可以采用内联也可以采用外联方式载入\n\n代码举例\n\n```html\n<div id=\"template-box\">\n    <!-- 纯内联样式 -->\n    <textarea name=\"js\">\n      var a = 'aaaa';\n      var b = 'bbbb';\n    </textarea>\n\n    <!-- 纯外联 -->\n    <textarea name=\"js\" data-src=\"./a.js,./b.js\" data-version=\"v1\"></textarea>\n\n    <!-- 复合内联外联 -->\n    <textarea name=\"js\" data-src=\"./a.css,./b.css\" data-version=\"v1\">\n      var a = 'aaaa';\n      var b = 'bbbb';\n    </textarea>\n</div>\n```\n\n对于内外联复合的脚本模板激活时，内联的脚本在外联的脚本载入完成后执行\n\n系统初始化时使用_$parseTemplate接口解析模版\n\n代码举例\n\n```javascript\nNEJ.define([\n    'util/template/tpl'\n],function(_t){\n    // 激活脚本\n    _t._$parseTemplate('template-box');\n\n    // TODO\n});\n```\n\n#### html\n\n外联模版集合，载入的结构会递归进行调用_$parseTemplate接口解析模版，项目中一般用于载入通用控件结构，html模版的data-src不支持多个模版用“,”分隔的形式\n\n代码举例\n\n```html\n<div id=\"template-box\">\n    <textarea name=\"html\" data-src=\"./a.html\" data-version=\"v1\"></textarea>\n    <textarea name=\"html\" data-src=\"./b.html\" data-version=\"v1\"></textarea>\n</div>\n```\n\n系统初始化时使用_$parseTemplate接口解析模版，如果要确保代码中能够使用外联的模版，则需要在document的ontemplateready事件中处理\n\n代码举例\n\n```javascript\nNEJ.define([\n    'base/event',\n    'util/template/tpl'\n],function(_v,_t){\n    // 载入外联模版集合\n    _t._$parseTemplate('template-box');\n\n    _v._$addEvent(\n        document,'templateready',function(){\n            // 这里可以保证外联的模板可用\n\n            // TODO\n        }\n    );\n\n    // TODO\n});\n```\n\n#### res\n\n外联文本资源，载入后作为txt类型的模版使用，需要指定id\n\n代码举例\n\n```html\n<div id=\"template-box\">\n    <textarea name=\"txt\" id=\"txt-0\" data-src=\"./a.html\" data-version=\"v1\"></textarea>\n    <textarea name=\"txt\" id=\"txt-1\" data-src=\"./b.html\" data-version=\"v1\"></textarea>\n</div>\n```\n\n后续通过_$getTextTemplate接口使用，如果要确保代码中能够使用外联的模版，则需要在document的ontemplateready事件中处理\n\n代码举例\n\n```javascript\nNEJ.define([\n    'util/template/tpl'\n],function(_t){\n    // 解析模版，支持textarea的批量解析\n    _t._$parseTemplate('template-box');\n\n    _v._$addEvent(\n        document,'templateready',function(){\n            // 这里可以保证外联的模板可用\n\n            // 根据模板ID取模板内容\n            // 返回字符串类型的模板内容\n            var _text0 = _t._$getTextTemplate('txt-0');\n            var _text1 = _t._$getTextTemplate('txt-1');\n\n            // TODO\n        }\n    );\n\n    // TODO\n});\n```\n\n## JST语法\n\n### 表达式\n\n#### ${}\n\n描述：求值表达式，表达式中不可以包含 “{”或者“}”\n\n语法：\n\n```html\n${expr}\n\n${expr|modifier}\n\n${expr|modifier1|modifier2|...|modifierN}\n\n${expr|modifier1:argExpr1_1}\n\n${expr|modifier1:argExpr1_1,argExpr1_2,...,argExpr1_N}\n\n${expr|modifier1:argExpr1_1|...|modifierN:argExprN_1,argExprN_2,...,argExprN_M}\n```\n\n范例：\n\n```html\n${customer.firstName}\n\n${customer.firstName|capitalize}\n\n${customer.firstName|default:\"no name\"|capitalize}\n\n${article.getCreationDate|default:new Date()|toCalendarControl:\"YYYY.MM.DD\",true,\"creation Date\"}\n\n${(lastQuarter.calcRevenue() - fixedCosts) / 10000}\n```\n\n#### ${% %}\n\n描述：求值表达式，表达式中可以包含 “{”或者“}”\n\n语法：\n\n```html\n${% expr %}\n```\n\n范例：\n\n```html\n${% emitLink(\"Solution and Products\", {color: \"red\", blink: false}) %}\n```\n\n### 语句\n\n#### list break\n\n描述：遍历数组\n\n语法1：\n\n```html\n{list seq as varName}\n    ...\n{break}\n    ...\n{/list}\n```\n\n范例1：\n\n```html\n{list [\"aaa\", \"bbbb\", \"ccccc\"] as x}\n  ${x_index}/${x_length}:${x}<br/>\n{/list}\n```\n\n备注：\n\n* x_index为内置变量，值为循环的索引值。\n* x_length为内置变量，值为列表长度， 上例中值为3。\n\n语法2：\n\n```html\n{list from..to as varName}\n    ...\n{/list}\n```\n\n备注：循环时包含from和to值\n\n范例2：\n\n```html\n{list 2..10 as x}\n    ${x_index}/${x_length}:${x}<br/>\n{/list}\n```\n\n备注：\n\n* x_index为内置变量，值为循环的索引值。\n* x_length为内置变量，值为列表长度， 上例中值为9。\n\n#### for forelse\n\n描述：遍历HASH表\n\n语法：\n\n```html\n{for varName in hash}\n    ...\n{forelse}\n    ...\n{/for}\n```\n\n注：forelse 子语句为可选\n\n范例：\n\n```html\n{for x in {a:\"aaa\", b:\"bbbb\", c:\"ccccc\"}}\n    ${x_key} - ${x}<br/>\n{forelse}\n    no pro\n{/for}\n```\n\n注：x_key为内置变量，值为当前项的键值。\n\n#### if elseif else\n\n描述：条件控制语句\n\n语法：\n\n```html\n{if expr}\n    ...\n{elseif expr}\n    ...\n{else}\n    ...\n{/if}\n```\n\n注：elseif、else 子语句为可选\n\n范例：\n\n```html\n{if gender == 1}\n    男\n{elseif gender == 0}\n    女\n{else}\n    春哥\n{/if}\n```\n\n#### var\n\n描述：变量定义\n\n语法：\n\n```html\n{var varName}\n\n{var varName = expr}\n```\n\n范例：\n\n```html\n{var test = \"sssssss\"}\n```\n\n#### macro\n\n描述：宏定义\n\n语法：\n\n```html\n{macro macroName(arg1, arg2, ... argN)}\n    ... body of the macro ...\n{/macro}\n```\n\n范例：\n\n```html\n{macro htmlList(dataList, optionalListType)}\n    {var listType = optionalListType != null ? optionalListType : \"ul\"}\n    <${listType}>\n        {for item in dataList}\n            <li>${item}</li>\n        {/for}\n    </${listType}>\n{/macro}\n```\n\n调用宏：\n\n```html\n${htmlList([\"首页\", \"日志\"，\"相册\", \"关于我\"])}\n```\n\n输出：\n\n```html\n<ul>\n    <li>首页</li>\n    <li>日志</li>\n    <li>相册</li>\n    <li>关于我</li>\n</ul>\n```\n\n#### cdata\n\n描述：文本块，内容不做语法解析\n\n语法：\n\n```html\n{cdata}\n    ...no parsed text ...\n{/cdata}\n```\n\n或\n\n```html\n{cdata EOF}\n    ...no parsed text ...\nEOF\n```\n\n范例：\n\n```html\n{cdata}\n    ${customer.firstName}${customer.lastName}\n{/cdata}\n```\n\n或\n\n```html\n{cdata END_OF_CDATA_SECTION}\n    ${customer.firstName}${customer.lastName}\nEND_OF_CDATA_SECTION\n```\n\n输出：${customer.firstName}${customer.lastName}\n\n#### minify\n\n描述：压缩文本内容，内容不做语法解析\n\n语法：\n\n```html\n{minify}\n    ...multi-line text which will be stripped of line-breaks...\n{/minify}\n```\n\n或\n\n```html\n{minify EOF}\n    ...multi-line text which will be stripped of line-breaks...\nEOF\n```\n\n范例：\n\n```html\n{minify}\n    no parsed\n    text\n    and\n    merge\n    one\n    line\n{/minify}\n```\n\n或\n\n```html\n{minify EOF}\n    no parsed\n    text\n    and\n    merge\n    one\n    line\nEOF\n```\n\n输出：no parsed text and merge one line\n\n#### eval\n\n描述：执行javascript语句，不做语法解析\n\n语法：\n\n```html\n{eval}\n    ...javascript statement...\n{/eval}\n```\n\n或\n\n```html\n{eval EOF}\n    ...javascript statement...\nEOF\n```\n\n范例：\n\n```html\n{eval}\n    var a = \"aaaa\";\n    alert(a);\n    function b(arg){\n        alert(arg);\n    }\n{/eval}\n```\n\n或\n\n```html\n{eval EOF}\n    var a = \"aaaa\";\n    alert(a);\n    function b(arg){\n        alert(arg);\n    }\nEOF\n```\n\n### 扩展\n\n#### rand\n\n描述：随机一个指定长度的纯数字的串\n\n语法：\n\n```html\n${number_expr|rand}\n```\n\n范例：\n\n```html\n${10|rand}\n```\n\n输出：3456785438\n\n#### escape\n\n描述：编码字符串\n\n语法：\n\n```html\n${expr|escape}\n```\n\n范例：\n\n```html\n${\"<div>1234<a href=\"#\">163</a></div>\"|escape}\n```\n\n输出：&amp;lt;div&amp;gt;1234&amp;lt;a href=\"#\"&amp;gt;163&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;\n\n#### format\n\n描述：格式化日期\n\n语法：\n\n```html\n${data_expr|format:format_expr}\n```\n\n范例：\n\n```html\n${new Date()|format:\"yyyy-MM-dd HH:mm:ss\"}\n```\n\n输出：2012-06-13 16:30:55\n\n#### default\n\n描述：指定默认值\n\n语法：\n\n```html\n${expr|default:default_expr}\n```\n\n范例：\n\n```html\n${null|default:\"default value\"}\n```\n\n输出：default value\n\n注：当expr为undefiend,null,false,0或者空字符串时取默认值\n\n## ITEM控件\n\nITEM控件提供了结构+逻辑的缓存功能，适合于列表项带复杂逻辑的模版，一般使用ntp模版来封装结构，列表类的ITEM基类抽象在ui/item/list模块中实现，因为ITEM控件也是UI控件，所以遵循[UI控件](./WIDGET.md)的规则\n\n如下图所示的评论列表中，每一项评论又具有回复列表、回复和删除功能，我们可以将这种结构做成ITEM模版\n\n![评论列表](http://img0.ph.126.net/EiEyOdGSqY0PASizUZMynA==/6608813650352806767.png)\n\nITEM控件的目录结构\n\n```\n  comment\n     | - comment.css    评论项样式\n     | - comment.html   评论项结构\n     | - comment.js     评论项逻辑\n```\n\ncomment.html文件使用ntp类型的模版做结构\n\n```html\n<div class=\"m-cmt\">\n  <div class=\"fce\"><img class=\"j-flag\"/></div>\n  <div class=\"box\">\n    <div class=\"ttl j-flag\"><!-- 用户占位 --></div>\n    <div class=\"cnt j-flag\"><!-- 内容占位 --></div>\n    <div class=\"act j-flag\">\n      <a href=\"#\" data-action=\"reply\">回复</a>\n      <a href=\"#\" data-action=\"delete\">删除</a>\n    </div>\n  </div>\n</div>\n```\n\ncomment.js文件继承ui/item/list模块的\\_$$ListItem类进行扩展\n\n```javascript\nNEJ.define([\n    'base/klass',\n    'base/element',\n    'base/event',\n    'ui/item/list',\n    'util/template/tpl',\n    'text!./comment.css',\n    'text!./comment.html'\n],function(_k,_e,_v,_i,_t,_css,_html,_p,_o,_f,_r){\n    var _pro;\n\n    // 列表项构造\n    _p._$$CommentItem = _k._$klass();\n    _pro = _p._$$CommentItem._$extend(_i._$$ListItem);\n\n    // 外观\n    _pro.__initXGui = (function(){\n        var _seed_css = _e._$pushCSSText(_css),\n            _seed_html = _e._$addNodeTemplate(_html);\n        return function(){\n            this.__seed_css = _seed_css;\n            this.__seed_html = _seed_html;\n        };\n    })();\n\n    // 结构\n    _pro.__initNode = function(){\n        this.__super();\n        // 0 - 头像图片节点\n        // 1 - 用户名节点\n        // 2 - 内容节点\n        // 3 - 操作行为节点\n        var _list = _e._$getByClassName(\n            this.__body,'j-flag'\n        );\n        this.__nface = _list[0];\n        this.__nuser = _list[1];\n        this.__ncont = _list[2];\n        // 事件\n        _v._$addEvent(\n            _list[3],'click',\n            this.__onAction._$bind(this)\n        );\n    };\n\n    // 刷新\n    _pro.__doRefresh = function(_data){\n        this.__nface.src = _data.face;\n        this.__nuser.innerHTML = _data.username;\n        this.__ncont.innerHTML = _data.content;\n        // 子评论列表\n        if (!!_data.replies){\n            // 子评论构造同当前评论项\n            this.__items = _t._$getItemTemplate(\n                _data.replies,this.constructor,{\n                    parent:this.__body,\n                    onreply:this.__onReply._$bind(this),\n                    ondelete:this.__onDelete._$bind(this)\n                }\n            );\n        }\n    };\n\n    // 操作\n    _pro.__onAction = function(_event){\n        var _node = _v._$getElement(_event,'d:action');\n        if (!_node) return;\n        // 操作\n        switch(_e._$dataset(_node,'action')){\n            case 'reply':\n                // 分配回复编辑器控件\n                // 触发onreply事件\n                // TODO\n            break;\n            case 'delete':\n                // 删除确认\n                // 触发ondelete事件\n                // TODO\n            break;\n        }\n    };\n\n    // TODO\n\n    return _p;\n});\n```\n\n在上层应用中使用_$getItemTemplate来分配ITEM控件列表\n\n```javascript\nNEJ.define([\n    'util/template/tpl',\n    '/path/to/comment.js'\n],function(_t,_i){\n\n    // TODO\n\n    var _list = _t._$getItemTemplate(\n        _data.replies,this.constructor,{\n            parent:'list-box',\n            onreply:function(_data){\n                // TODO\n            },\n            ondelete:function(_data){\n                // TODO\n            }\n        }\n    );\n\n});\n```\n"
  },
  {
    "path": "doc/WIDGET.md",
    "content": "# 控件系统\n\n## 概述\n\n控件系统主要用来解决系统复杂性的问题，使得系统不会因为变得复杂而不可控，同时保证其维护性和扩展性\n\nNEJ框架提供了基于常规面向对象的思想构建的控件系统，主要用于：\n\n* 提供通用解决方案的封装支持\n* 提供核心功能、分析设计的重用\n* 提供跨平台控件及API的支持\n\n\n## 类模型\n\n因为JavaScript本身没有提供类的概念，在控件系统中提供了一套类模型的解决方案，用以模拟常规面向对象语言中的“类”的概念。\n\n类模型的实现见NEJ框架的base/klass模块\n\n### 类定义\n\n控件提供使用统一的类定义接口 \\_$klass 来定义一个类，通过此接口定义的类才具备以下的继承、初始化等特性\n\n```javascript\nNEJ.define([\n    'base/klass'\n],function(_k,_p){\n    // 定义一个类\n    _p._$$Klass = _k._$klass();\n\n    // TODO\n    \n    return _p;\n});\n```\n\n### 类继承\n\n使用 \\_$klass 定义的类可以使用 \\_$extend 接口来继承其他父类\n\n```javascript\nNEJ.define([\n    'base/klass'\n],function(_k,_p){\n    // 定义一个类\n    _p._$$Klass = _k._$klass();\n    // 继承其他类\n    var pro = _p._$$Klass._$extend(Super);\n\n    // TODO\n    \n    return _p;\n});\n```\n\n### 类构造\n\n使用 \\_$klass 定义的类统一使用 \\_\\_init 接口来初始化类，所有子类的接口均可以使用 this.\\_\\_super 方式调用父类同名接口\n\n```javascript\nNEJ.define([\n    'base/klass'\n],function(_k,_p){\n    // 定义一个类\n    _p._$$Klass = _k._$klass();\n    // 继承其他类\n    var pro = _p._$$Klass._$extend(Super);\n    // 初始化\n    pro.__init = function(){\n        // 调用父类的__init\n        this.__super();\n        // TODO something\n    };\n    \n    // TODO\n    \n    return _p;\n});\n```\n\n### 类扩展\n\n类的所有方法均定义在类函数的 prototype 对象上\n\n```javascript\nNEJ.define([\n    'base/klass'\n],function(_k,_p){\n    // 定义一个类\n    _p._$$Klass = _k._$klass();\n    // 继承其他类\n    var pro = _p._$$Klass._$extend(Super);\n    // 初始化\n    pro.__init = function(){\n        // 调用父类的__init\n        this.__super();\n        // TODO something\n    };\n\n    // private 方法\n    pro._privateMethod = function(){\n\n    };\n    // protected 方法\n    pro.__protectedMethod = function(){\n        // TODO\n    };\n    // public 方法\n    pro._$publicMethod = function(){\n        // TODO\n    };\n\n    // TODO\n    \n    return _p;\n});\n```\n\n### 类规范\n\n1. 类命名\n\n   类命名使用前缀\\_$$标识，首字母大写，驼峰式，如\\_$$Klass，\\_$$OneKlass\n\n2. 类方法\n\n   方法分为私有、保护、公共方法三类，各类方法的前缀标识如下\n\n   * 私有方法使用\\_(单个下划线)作为前缀，如\\_privateMethod\n   * 受保护的方法使用\\_\\_(两个下划线)作为前缀，如\\_\\_protectedMethod\n   * 公共的方法使用\\_$(下划线+美元符)作为前缀，如\\_$publicMethod\n\n   方法的命名首字母小写，驼峰式，如\\_$myApi，\\_\\_myApi，\\_myApi\n\n## 控件模型\n\n控件模型使用类模型来实现，基于类模型的基础做扩展，主要在util/event模块中实现；控件采用分配回收机制，因此控件的生命周期包括以下三个阶段：\n\n1. 控件创建：首次使用时控件创建阶段，主要用于构建控件相关结构、数据等\n2. 控件重置：重复使用时控件重置阶段，主要用于处理外部输入数据、事件侦测等\n3. 控件回收：回收不用时控件销毁阶段，主要用于销毁重置阶段产生的结构、数据等\n\n### 控件定义\n\n所有的控件均继承自 util/event 模块的 _$$EventTarget 类\n\n```javascript\nNEJ.define([\n    'base/klass',\n    'util/event'\n],function(_k,_t,_p){\n    var _pro;\n    // 定义控件\n    _p._$$Widget = _k._$klass();\n    // 继承_$$EventTarget\n    _pro = _p._$$Widget._$extend(_t._$$EventTarget);\n\n    // TODO\n\n    return _p;\n});\n```\n\n### 接口重写\n\n控件采用分配回收重用机制，因此控件需实现\\_\\_init、\\_\\_reset、\\_\\_destroy接口\n\n```javascript\nNEJ.define([\n    'base/klass',\n    'util/event'\n],function(_k,_t,_p){\n    var _pro;\n    // 定义控件\n    _p._$$Widget = _k._$klass();\n    // 继承_$$EventTarget\n    _pro = _p._$$Widget._$extend(_t._$$EventTarget);\n    // 控件首次创建构造过程\n    _pro.__init = function(){\n        this.__super();\n        // TODO\n    };\n    // 控件重复使用重置过程\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        // TODO\n    };\n    // 控件回收销毁过程\n    _pro.__destroy = function(){\n        this.__super();\n        // TODO\n    };\n\n    // TODO\n\n    return _p;\n});\n```\n\n### 扩展实现\n\n其他扩展的业务逻辑根据控件实际需求实现\n\n```javascript\nNEJ.define([\n    'base/klass',\n    'util/event'\n],function(_k,_t,_p){\n    var _pro;\n    // 定义控件\n    _p._$$Widget = _k._$klass();\n    // 继承_$$EventTarget\n    _pro = _p._$$Widget._$extend(_t._$$EventTarget);\n    // 控件首次创建构造过程\n    _pro.__init = function(){\n        this.__super();\n        // TODO\n    };\n    // 控件重复使用重置过程\n    // 重置过程可以接受到分配控件时输入的配置信息\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        // TODO\n    };\n    // 控件回收销毁过程\n    _pro.__destroy = function(){\n        this.__super();\n        // TODO\n    };\n\n    // 扩展私有接口\n    _pro._myPrivateMethod = function(){\n        // TODO\n    };\n    // 扩展保护接口\n    _pro.__myProtectedMethod = function(){\n        // TODO\n    };\n    // 扩展对外接口\n    _pro._$myPublicMethod = function(){\n        // TODO\n    };\n\n    // TODO\n\n    return _p;\n});\n```\n\n### 事件支持\n\n控件支持自定义事件的触发，在控件的业务逻辑中可根据实际需求通过 \\_$dispatchEvent 接口触发自定义事件来与外界进行交互\n\n```javascript\nNEJ.define([\n    'base/klass',\n    'util/event'\n],function(_k,_t,_p){\n    var _pro;\n    // 定义控件\n    _p._$$Widget = _k._$klass();\n    // 继承_$$EventTarget\n    _pro = _p._$$Widget._$extend(_t._$$EventTarget);\n    // 控件首次创建构造过程\n    _pro.__init = function(){\n        this.__super();\n        // TODO\n    };\n    // 控件重复使用重置过程\n    // 重置过程可以接受到分配控件时输入的配置信息\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        // TODO\n    };\n    // 控件回收销毁过程\n    _pro.__destroy = function(){\n        this.__super();\n        // TODO\n    };\n\n    // 扩展私有接口\n    _pro._myPrivateMethod = function(){\n        // TODO\n        // 触发自定义的onchange事件\n        this._$dispatchEvent(\n            'onchange',{\n                x:'xxxxx',\n                y:'yyyyyyy'\n            }\n        );\n    };\n    // 扩展保护接口\n    _pro.__myProtectedMethod = function(){\n        // TODO\n        // 触发自定义的onupdate事件\n        this._$dispatchEvent(\n            'onupdate',{\n                a:'aaaa',\n                b:'bbbbbbb'\n            }\n        );\n    };\n    // 扩展对外接口\n    _pro._$myPublicMethod = function(){\n        // TODO\n    };\n\n    // TODO\n\n    return _p;\n});\n```\n\n### 平台适配\n\n控件的平台适配规则遵循《[平台适配系统](./PLATFORM.md)》的规范，可以按照以下步骤实现：\n\n1. 在控件实现文件处构建平台适配目录platform，可以通过nej工具集中nej-widget指令来自动生成控件目录结构，或者使用nej-patch指令来自动生成platform目录结构，如\n\n    ```\n      widget\n        | - widget.js\n        | - platform\n                | - widget.js\n                | - widget.patch.js\n    ```\n\n2. 提取控件涉及的存在平台差异的API，在platform/widget.js中根据W3C/ES规范实现API\n\n    ```javascript\n    NEJ.define([\n        'base/platform'\n    ],function(_m,_p){\n        // 存在平台差异的API\n        _p.__api1 = function(){\n            // TODO\n        };\n        // 存在平台差异的API\n        _p.__api2 = function(){\n            // TODO\n        }\n        // 返回平台差异API集合\n        return _p;\n    });\n    ```\n\n3. 根据平台差异，在platform/widget.patch.js文件中实现各平台的差异化逻辑\n\n    ```javascript\n    NEJ.define([\n        './widget.js'   // 这里注入标准API集合\n    ],function(_h){\n        // 根据平台特点重写API实现\n        NEJ.patch('TR<=2.0',function(){\n            // for ie6-\n            _h.__api1 = function(){\n                // TODO\n            };\n        });\n\n        // 根据平台特点采用AOP方式切入平台逻辑\n        NEJ.patch('WR',function(){\n            // for webkit\n            _h.__api2 = _h.__api2._$aop(\n                function(_event){\n                    // 标准逻辑之前处理业务逻辑\n                    // _event.args\n                    // _event.value\n                    // _event.stopped\n                    // TODO\n                },\n                function(_event){\n                    // 标准逻辑之后处理业务逻辑\n                    // _event.args\n                    // _event.value\n                    // _event.stopped\n                    // TODO\n                }\n            );\n        });\n\n        // 这里必须返回注入的标准API集合\n        return _h;\n    });\n    ```\n\n4. 控件中使用{platform}注入平台适配API使用\n\n    ```javascript\n    NEJ.define([\n        'base/klass',\n        'util/event',\n        '{platform}widget.js'\n    ],function(_k,_t,_h,_p){\n        var _pro;\n        // 定义控件\n        _p._$$Widget = _k._$klass();\n        // 继承_$$EventTarget\n        _pro = _p._$$Widget._$extend(_t._$$EventTarget);\n        // 控件首次创建构造过程\n        _pro.__init = function(){\n            this.__super();\n            // TODO\n        };\n        // 控件重复使用重置过程\n        // 重置过程可以接受到分配控件时输入的配置信息\n        _pro.__reset = function(_options){\n            this.__super(_options);\n            // TODO\n        };\n        // 控件回收销毁过程\n        _pro.__destroy = function(){\n            this.__super();\n            // TODO\n        };\n\n        // 扩展私有接口\n        _pro._myPrivateMethod = function(){\n            // 使用平台适配接口\n            _h.__api1();\n\n            // TODO\n            // 触发自定义的onchange事件\n            this._$dispatchEvent(\n                'onchange',{\n                    x:'xxxxx',\n                    y:'yyyyyyy'\n                }\n            );\n        };\n        // 扩展保护接口\n        _pro.__myProtectedMethod = function(){\n            // TODO\n            // 触发自定义的onupdate事件\n            this._$dispatchEvent(\n                'onupdate',{\n                    a:'aaaa',\n                    b:'bbbbbbb'\n                }\n            );\n        };\n        // 扩展对外接口\n        _pro._$myPublicMethod = function(){\n            // 使用平台适配接口\n            _h.__api2();\n\n            // TODO\n        };\n\n        // TODO\n\n        return _p;\n    });\n    ```\n\n### 控件使用\n\n控件使用分配回收机制而非 new 的方式使用\n\n```javascript\nNEJ.define([\n    '/path/to/widget.js'\n],function(_t){\n    // 分配控件\n    var _widget = _t._$$Widget._$allocate({\n        a:'aaaaaaaa',\n        b:'bbbbbbbbbbb',\n        c:'ccccccccccccc',\n        onchange:function(_event){\n            // 控件支持的事件\n            // _event.x\n            // _event.y\n\n            // TODO\n        },\n        onupdate:function(_event){\n            // 控件支持的事件\n            // _event.a\n            // _event.b\n\n            // TODO\n        }\n    });\n\n    // 外界可以调用控件的public方法\n    _widget._$myPublicMethod();\n\n    // 回收控件\n    // 注意这里必须将原控件持有的引用置空\n    _widget = _widget._$recycle();\n    // 或者\n    _widget._$recycle();\n    _widget = null;\n});\n```\n\n## 控件分类\n\n控件根据其封装元素的差异可以分为通用控件和UI控件两类\n\n* 通用控件：此类控件关注功能业务逻辑的实现，不关注视觉效果\n* UI控件：此类控件会构建一套默认的视觉效果，具体功能逻辑由与之匹配的通用控件来实现\n\n由于UI控件在实际项目中差异性比较大，因此NEJ框架会主要关注通用控件的支持，项目中可以根据通用控件结合实际项目视觉效果来实现项目相关的UI控件\n\n### 通用控件\n\n通用控件只需遵循[控件模型](#控件模型)实现即可\n\n### UI控件\n\nUI控件基于控件模型扩展而来，其抽象实现在 ui/base 模块中的 \\_$$Abstract 类，UI控件的主要元素包括：\n\n* 样式：控件展示效果样式，独立在控件对应的css文件中\n* 结构：控件组成结构，独立在控件对应的html文件中\n* 逻辑：控件逻辑实现，独立在控件对应的javascript文件中\n\n一个UI控件典型的目录结构为\n\n```\n    widget\n      | - widget.css\n      | - widget.html\n      | - widget.js\n```\n\n#### 样式\n\n每个UI控件都使用一个唯一的样式标识，以防止与其他控件样式冲突，样式文件范例如下：\n\n```css\n.#<uispace>-parent{position:relative;}\n.#<uispace>{position:absolute;border:1px solid #aaa;background:#fff;text-align:left;visibility:hidden;}\n.#<uispace> .zitm{height:20px;line-height:20px;cursor:default;}\n.#<uispace> .js-selected{background:#1257F9;}\n```\n\n这里可以使用 #&lt;KEY&gt; 格式的简单模板来做数据占位，其中\n\n* \\#&lt;uispace&gt; - 表示自动生成的样式标识名称\n* \\#&lt;uispace&gt;-parent - 表示控件节点的父容器节点的样式\n* 其他参数可以使用#&lt;KEY&gt;来占位，后续使用时输入{KEY:'XXXXX'}的数据即可\n\n#### 结构\n\n每个UI控件可以关联若干的结构模板，模板规则遵循NEJ的[模板系统](./TEMPLATE.md)规范\n\n单个模板文件范例\n\n```html\n<div>\n  <div class=\"zbar\">\n    <div class=\"zttl\">标题</div>\n  </div>\n  <div class=\"zcnt\"></div>\n  <span class=\"zcls\" title=\"关闭窗体\">×</span>\n</div>\n```\n\n多个模板文件范例，模板的ID支持使用 #&lt;KEY&gt; 形式的简单模板做ID占位\n\n```html\n<textarea name='jst' id='#<icmd>'>\n{list xlist as x}\n  <div class=\"zitm zbg ${'js-'|seed}\" data-command=\"${x.cmd}\" title=\"${x.txt}\">\n    <div class=\"zicn zbg ${x.icn}\">&nbsp;</div>\n    <div class=\"ztxt\">${x.txt}</div>\n  </div>\n{/list}\n{if defined(\"hr\")&&!!hr}\n  <div class=\"zbg zisp\">&nbsp;</div>\n{/if}\n</textarea>\n\n<textarea name='jst' id='#<ifnt>'>\n  <div class=\"zsel ${icn} ${'js-'|seed}\" data-command=\"${cmd}\">\n    <span class=\"${'js-t-'|seed}\">${txt}</span>\n    <span class=\"zarw zbg\">&nbsp;</span>\n  </div>\n</textarea>\n\n<textarea name='jst' id='#<iedt>'>\n  <div>\n    <div class=\"ztbar\">${toolbar}</div>\n    <div class=\"zarea\"></div>\n  </div>\n</textarea>\n```\n\n#### 逻辑\n\n逻辑部分主要用来实现UI控件的核心逻辑，主要分以下几部分功能\n\n* 注入样式处理\n* 注入结构处理\n* 控件初始化\n\n##### 注入样式\n\n根据[依赖系统](./DEPENDENCY.md)规则，UI控件使用 text! 注入样式，注入的样式通过 base/element 模块中的 \\_$pushCSSText 接口做预处理，并返回自动生成的控件样式标识\n\n```javascript\nNEJ.define([\n    'base/element',\n    'ui/base',\n    'text!./widget.css'\n],function(_e,_i,_css,_p){\n    // 将注入的样式做预处理后缓存\n    var _seed_css = _e._$pushCSSText(_css);\n\n    // TODO\n});\n```\n\n如果样式中已做了样式标识无需自动生成则只需缓存样式即可，如\n\n```css\n.ui-suggest-parent{position:relative;}\n.ui-suggest{position:absolute;border:1px solid #aaa;background:#fff;text-align:left;visibility:hidden;}\n.ui-suggest .zitm{height:20px;line-height:20px;cursor:default;}\n.ui-suggest .js-selected{background:#1257F9;}\n```\n\n```javascript\nNEJ.define([\n    'base/element',\n    'ui/base',\n    'text!./widget.css'\n],function(_e,_i,_css,_p){\n    // 将注入的样式缓存\n    _e._$pushCSSText(_css);\n\n    // TODO\n});\n```\n\n##### 注入结构\n\n根据[依赖系统](./DEPENDENCY.md)规则，UI控件使用 text! 注入结构，注入的结构符合[模板系统](./TEMPLATE.md)规则，后续使用 util/template/tpl 模块中的模板处理接口做处理\n\n单个模板结构注入\n\n```javascript\nNEJ.define([\n    'base/element',\n    'util/template/tpl',\n    'ui/base',\n    'text!./widget.css',\n    'text!./widget.html'\n],function(_e,_t,_i,_css,_html,_p){\n    // 将注入的样式做预处理后缓存\n    var _seed_css = _e._$pushCSSText(_css),\n        _seed_html = _t._$addNodeTemplate(_html);\n\n    // TODO\n});\n```\n\n多个模板结构注入\n\n```javascript\nNEJ.define([\n    'base/element',\n    'util/template/tpl',\n    'ui/base',\n    'text!./widget.css',\n    'text!./widget.html'\n],function(_e,_t,_i,_css,_html,_p){\n    // 将注入的样式做预处理后缓存\n    var _seed_css = _e._$pushCSSText(_css);\n\n    // 这里可以自动生成模板ID\n    // 返回 {icmd:'tpl-127363653',ifnt:'tpl-5985857444',iedt:'tpl-48763635374'}\n    var _seed = _t._$parseUITemplate(_html);\n\n    // 这里也可以自己指定模板ID\n    // 可以指定全部的ID，也可以指定某几个，未指定的ID自动生成\n    var _seed = _t._$parseUITemplate(_html,{\n        icmd:'abc',\n        ifnt:'def',\n        iedt:'ghi'\n    });\n\n    // TODO\n});\n```\n\n##### 逻辑实现\n\nUI控件的逻辑实现主要扩展自 ui/base 模块中的 \\_$$Abstract 类，需要实现外观的设置和结构的初始化\n\n1. 初始化外观\n\n    ```javascript\n    NEJ.define([\n        'base/klass',\n        'base/element',\n        'util/template/tpl',\n        'ui/base',\n        'text!./widget.css',\n        'text!./widget.html'\n    ],function(_k,_e,_t,_i,_css,_html,_p){\n        var _pro;\n\n        // 定义UI控件\n        _p._$$UIWidget = _k._$klass();\n        _pro = _p._$$UIWidget._$extend(_i._$$Abstract);\n\n        // 按需完成通用控件接口重写\n        // _pro.__init ...\n        // _pro.__reset ...\n        // _pro.__destroy ...\n\n        // 初始化外观\n        // 此过程只会在控件第一次创建时进入\n        _pro.__initXGui = (function(){\n            // 将注入的样式/结构做预处理后缓存\n            var _seed_css = _e._$pushCSSText(_css),\n                _seed_html = _t._$addNodeTemplate(_html);\n            return function(){\n                this.__seed_css = _seed_css;\n                this.__seed_html = _seed_html;\n            };\n        })();\n\n        // TODO\n\n        return _p;\n    });\n    ```\n\n2. 初始化结构\n\n    ```javascript\n    NEJ.define([\n        'base/klass',\n        'base/element',\n        'util/template/tpl',\n        'ui/base',\n        'text!./widget.css',\n        'text!./widget.html'\n    ],function(_k,_e,_t,_i,_css,_html,_p){\n        var _pro;\n\n        // 定义UI控件\n        _p._$$UIWidget = _k._$klass();\n        _pro = _p._$$UIWidget._$extend(_i._$$Abstract);\n\n        // 按需完成通用控件接口重写\n        // _pro.__init ...\n        // _pro.__reset ...\n        // _pro.__destroy ...\n\n        // 初始化外观\n        // 此过程只会在控件第一次创建时进入\n        _pro.__initXGui = (function(){\n            // 将注入的样式/结构做预处理后缓存\n            var _seed_css = _e._$pushCSSText(_css),\n                _seed_html = _t._$addNodeTemplate(_html);\n            return function(){\n                this.__seed_css = _seed_css;\n                this.__seed_html = _seed_html;\n            };\n        })();\n\n        // 初始化结构\n        // 此过程只会在控件第一次创建时进入\n        _pro.__initNode = function(){\n            // 调用父类接口通过提供的__seed_html构建控件结构\n            // 构建好的控件结构可以通过this.__body访问\n            this.__super();\n\n            // TODO\n        };\n\n        // TODO\n\n        return _p;\n    });\n    ```\n\n3. 功能实现\n\n    ```javascript\n    NEJ.define([\n        'base/klass',\n        'base/element',\n        'util/template/tpl',\n        'ui/base',\n        'text!./widget.css',\n        'text!./widget.html'\n    ],function(_k,_e,_t,_i,_css,_html,_p){\n        var _pro;\n\n        // 定义UI控件\n        _p._$$UIWidget = _k._$klass();\n        _pro = _p._$$UIWidget._$extend(_i._$$Abstract);\n\n        // 按需完成通用控件接口重写\n        // _pro.__init ...\n        // _pro.__reset ...\n        // _pro.__destroy ...\n\n        // 初始化外观\n        // 此过程只会在控件第一次创建时进入\n        _pro.__initXGui = (function(){\n            // 将注入的样式/结构做预处理后缓存\n            var _seed_css = _e._$pushCSSText(_css),\n                _seed_html = _t._$addNodeTemplate(_html);\n            return function(){\n                this.__seed_css = _seed_css;\n                this.__seed_html = _seed_html;\n            };\n        })();\n\n        // 初始化结构\n        // 此过程只会在控件第一次创建时进入\n        _pro.__initNode = function(){\n            // 调用父类接口通过提供的__seed_html构建控件结构\n            // 构建好的控件结构可以通过this.__body访问\n            this.__super();\n\n            // TODO\n        };\n\n        // 实现控件核心功能\n        _pro._myPrivateMethod = function(){\n            // TODO\n        };\n        _pro.__myProtectedMethod = function(){\n            // TODO\n        };\n        _pro._$myPublicMethod = function(){\n            // TODO\n        };\n\n        // TODO\n\n        return _p;\n    });\n    ```\n\n##### 控件使用\n\n控件的使用同通用控件，这里需要注意的是UI控件需要输入parent配置参数才能在页面上渲染出来，否则构建的控件只存在于内存中，页面上无法看到\n\n```javascript\nNEJ.define([\n    '/path/to/ui/widget.js'\n],function(_i){\n    // 分配控件\n    var _uiwidget = _i._$$UIWidget._$allocate({\n        parent:document.body,  // 注意这里输入parent\n        clazz:'m-ui-widget'\n    });\n\n    // 回收控件\n    _uiwidget = _uiwidget._$recycle();\n});\n```\n\n## 控件规范\n\n项目过程中如果觉得有些控件可以通用，分享给其他项目使用，可以将控件提交到NEJ控件仓库，提交的控件遵循以下规范\n\n### 目录规范\n\n提交的通用控件目录结构如下所示（注：目录及文件命名中不得出现\".\"等特殊字符）\n\n```\n  widget\n    | - test\n    | - demo\n    | - platform\n    | - widget.js\n```\n\n提交的UI控件的目录结构为\n\n```\n  widget\n    | - test\n    | - demo\n    | - platform\n    | - widget.js\n    | - widget.css\n    | - widget.html\n```\n\n#### test\n\n用于自动化测试控件的代码，后期会统一规范控件的测试方式 （TODO：测试规范）\n\n#### demo\n\n用于放置当前控件的使用场景及使用范例\n\n#### platform\n\n根据NEJ[平台适配系统](./PLATFORM.md)规则，如果控件需要做平台适配则在此目录下实现适配接口，如果无需平台适配则可以不提交此目录\n\n#### widget.css\n\n控件关联的样式文件，如无关联样式可不提交此文件\n\n#### widget.html\n\n控件关联的结构文件，遵循NEJ[模板系统](./TEMPLATE.md)规范，如无关联结构可不提交此文件\n\n#### widget.js\n\n控件核心业务逻辑实现文件\n\n\n### 注释规范\n\n所有注释遵循[JSDOC3](http://usejsdoc.org/)规范，注释描述支持markerdown语法\n\n#### 文件注释\n\n文件起始位置注释文件的描述信息、作者、版本等\n\n```javascript\n    /*\n     * ------------------------------------------\n     * 控件描述内容\n     *\n     * @version  1.0\n     * @author   genify(caijf@corp.netease.com)\n     * ------------------------------------------\n     */\n```\n\n#### 模块注释\n\n使用@module标记注释当前文件的模块，模块名称可被[依赖系统](./DEPENDENCY.md)直接引入使用\n\n```javascript\n    /** @module util/event */\n```\n\n#### 类注释\n\n使用@class、@extends标记注释类及继承关系\n\n```javascript\n    /**\n     * 标签切换控件封装\n     *\n     * 结构举例\n     *\n     * ```html\n     *   <div id=\"box\">\n     *       <a>1</a>\n     *       <a>2</a>\n     *       <a class=\"js-disabled\">3</a>\n     *       <a>4</a>\n     *   </div>\n     * ```\n     *\n     * 脚本举例\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'util/tab/tab'\n     * ],function(_t){\n     *     // 实例化控件\n     *     var _tab = _t._$$Tab._$allocate({\n     *         list:_e._$getChildren('box'),\n     *         index:1,\n     *         onchange:function(_event){\n     *             // TODO\n     *         }\n     *     });\n     *     // 使用控件\n     *     _tab._$go(2);\n     * });\n     * ```\n     *\n     * @class   module:util/tab/tab._$$Tab\n     * @extends module:util/event._$$EventTarget\n     *\n     * @param    {Object}  config   - 可选配置参数\n     * @property {Array}   list     - 标签项列表\n     * @property {Number}  index    - 初始选中项索引值，默认为0\n     * @property {String}  event    - 触发选择事件名称，默认为click\n     * @property {Boolean} inverse  - 是否反过程，true表示选中时删除选中样式，否则选中时添加样式\n     * @property {String}  disabled - 选项禁用样式，默认为js-disabled\n     * @property {String}  selected - 选中样式名，默认为js-selected\n     */\n```\n\n#### 事件注释\n\n使用@event标记注释控件支持的事件\n\n```javascript\n    /**\n     * 标签切换事件，输入{last:1,index:5}\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'util/tab/tab'\n     * ],function(_t){\n     *     // 实例化控件\n     *     var _tab = _t._$$Tab._$allocate({\n     *         list:_e._$getChildren(_e._$get('box')),\n     *         index:1,\n     *         onchange:function(_event){\n     *             // _event.last   上一次的tab索引\n     *             // _event.index  需要切换到的tab索引\n     *             // _event.list   节点列表\n     *             // _event.data   节点上通过data-value设置的内容\n     *             // TODO\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @event    module:util/tab/tab._$$Tab#onchange\n     * @param    {Object}  event   - tab信息\n     * @property {Number}  last    - 上一次的tab索引\n     * @property {Number}  index   - 需要切换到的tab索引\n     * @property {Array}   list    - 节点列表\n     * @property {String}  data    - 节点上通过data-value设置的内容\n     * @property {Boolean} stopped - 是否阻止触发节点的默认事件，回调过程中如果设置为false则后续继续触发节点的默认事件\n     */\n```\n\n#### 方法注释\n\n使用@method标记注释控件接口，使用@private、@protected标记注释私有和受保护的方法\n\n```javascript\n    /**\n     * 设置标签选中状态\n     *\n     * @protected\n     * @method module:util/tab/tab._$$Tab#__doTabItemSelect\n     * @param  {Node}    arg0 - 标签节点\n     * @param  {Boolean} arg1 - 是否选中\n     * @return {Void}\n     */\n```\n\n```javascript\n    /**\n     * 切换到指定索引位置\n     *\n     * ```javascript\n     *   // 切换到索引为2的位置，如果当前索引为2则不触发回调\n     *   _tab._$go(2);\n     *   // 切换索引为2，如果当前索引为2也触发onchange回调\n     *   _tab._$go(2,true);\n     * ```\n     *\n     * @method module:util/tab/tab._$$Tab#_$go\n     * @param  {Number}  arg0 - 索引值\n     * @param  {Boolean} arg1 - 是否强行触发onchange事件\n     * @return {Void}\n     */\n```\n\n### 编码规范\n\n#### 前缀规范\n\n控件编码使用前缀标识变量使用范围\n\n| 前缀 | 说明 |\n| :--  | :--  |\n| \\_   | 私有属性、方法，局部变量，仅限于当前控件范围内使用 |\n| \\_\\_ | 受保护的属性、方法，控件范围及所有子类可使用 |\n| \\_$  | 对外属性、方法，控件外可直接调用 |\n| \\_$$ | 类名前缀，控件外可直接使用 |\n| on   | 事件名前缀，控件外可直接使用 |\n\n#### 命名规范\n\n控件命名遵循以下规则便于识别\n\n* 类名首字母大写，驼峰形式，如\\_$$MyClassName等\n* 属性、方法名首字母小写，驼峰形式，如 \\_myMethod、\\_\\_myProtectedMethod、\\_$doSomething等\n* 事件名称全小写，采用名称+动词形式，如 onchange、onlistload等\n\n\n"
  },
  {
    "path": "doc/guide/Build.Scalable.Web.System/Module.md",
    "content": "# 构建高可伸缩性的WEB交互式系统(2) - 模块的可伸缩性\n\n## 概述\n\n可伸缩性是一种对软件系统处理能力的设计指标，高可伸缩性代表一种弹性，在系统扩展过程中，能够保证旺盛的生命力，通过很少的改动，就能实现整个系统处理能力的增长。\n\n在系统设计的时候，充分地考虑系统的可伸缩性，一方面能够极大地减少日后的维护开销，并帮助决策者对于投资所能获得的回报进行更加精准的估计；另一方面，高可伸缩性的系统往往会具有更好的容灾能力，从而提供更好的用户体验。\n\nWEB交互式系统的可伸缩性主要体现在两个方面：\n\n* 平台的可伸缩性：随着WEB技术的发展，越来越多的平台开始使用WEB技术来构建系统，一方面不同的平台提供的环境支持存在着各种差异；另一方面随着平台的发展，不断的会有一些旧平台退出历史舞台，新平台转而成为主流平台；因此构建的WEB系统需要能够快速的响应此类变化就需要其具备良好的平台伸缩性\n* 模块的可伸缩性：随着系统功能不断增删更新需求的变化，系统可能会变得越来越复杂，冗余信息也可能会越来越多，改动所带来的影响范围也可能会越来越大，因此良好的模块伸缩性可保证系统具有良好的可维护性，让系统始终处于最佳状态\n\nWEB交互式系统的主要应用包括：\n\n* 桌面端/移动端网站类系统（如 [网易云课堂](http://study.163.com/)、[Lofter移动WEB版](http://www.lofter.com/)等）\n* 移动混合应用（如 [网易云相册IPad版](http://photo.163.com/cloudphotos/)、[Lofter](http://www.lofter.com/app)等）\n* 桌面混合应用（如 [网易云音乐PC版](http://music.163.com/#/download)、[网易邮箱助手](http://mailease.163.com/)等）\n\n## 模块的可伸缩性\n\nWEB交互式系统对模块的可伸缩性同样表现为：\n\n* 可扩展性：对于系统新增的功能需求能够快速响应支持\n* 可缩减性：对于系统退化的模块能够以最小的修改方式剔除\n\n这里我们提供一套模块调度的系统架构模式用于支持单页富应用系统的设计架构、模块拆分、模块重组、调度管理等功能\n\n### 模块\n\n这里我们定义的模块是指从系统中拆分出来的可与用户进行交互完成一部分完整功能的独立单元\n\n#### 模块组成\n\n因为这里描述的模块可独立与用户完成交互功能，因此模块会包含以下元素\n\n* 样式：定义模块的效果\n* 结构：定义模块的结构\n* 逻辑：实现模块的功能\n\n以上元素对于一个WEB系统开发者来说并不陌生，而我们只需要寻求一种形式将这些内容封装起来即可\n\n#### 模块封装\n\n从模块的组成我们可以看到系统中分离出来的模块可能会长成这个样子，比如module.html就是我们分离出来的一个模块\n\n当然这里也可以用脚本文件封装，样式和结构采用注入形式，我们这里以html文件封装举例\n\n```html\n<!-- 模块样式 -->\n<style>\n    .m-mdl-1 .a{color:#aaa;}\n    .m-mdl-1 .b{color:#bbb;}\n\n    /* 此处省略若干内容 */\n</style>\n\n<!-- 模块结构 -->\n<div class=\"m-mdl-1\">\n  <p class=\"a\">aaaaaaaaaaaaaaaaaaa</p>\n  <p class=\"b\">bbbbbbbbbbbbbbbbbbb</p>\n\n  <!-- 此处省略若干内容 -->\n</div>\n\n<!-- 模块逻辑 -->\n<script>\n    (function(){\n        var a = 'aaa';\n        var b = 'bbb';\n\n        // 此处省略若干内容\n    })();\n</script>\n```\n\n而这个模块在用户需要时加载到客户端，并展现出来跟用户进行交互，完成功能，但是我们会发现如果系统预加载了此模块或者模块在parse时这些内容会被直接执行，而这个结果并不是我们需要的，因此我们需要将模块的各元素文本化处理，文本化处理有多种方式，如作为文本script、textarea等标签内容，因此module.html里的模块我们可以封装成如下样子，以textarea举例：\n\n```html\n<!-- 模块样式 -->\n<textarea name=\"css\">\n    .m-mdl-1 .a{color:#aaa;}\n    .m-mdl-1 .b{color:#bbb;}\n\n    /* 此处省略若干内容 */\n</textarea>\n\n<!-- 模块结构 -->\n<textarea name=\"html\">\n    <div class=\"m-mdl-1\">\n      <p class=\"a\">aaaaaaaaaaaaaaaaaaa</p>\n      <p class=\"b\">bbbbbbbbbbbbbbbbbbb</p>\n\n      <!-- 此处省略若干内容 -->\n    </div>\n</textarea>\n\n<!-- 模块逻辑 -->\n<textarea name=\"js\">\n    (function(){\n        var a = 'aaa';\n        var b = 'bbb';\n\n        // 此处省略若干内容\n    })();\n</textarea>\n```\n\n### 管理依赖\n\n从系统中拆分出来的模块之间是存在有一定关系的，如一个模块的呈现必须依赖另外一个模块的呈现，下面我们会以一个简单的例子来讲解模块之间的依赖管理，如下图是我们的一个单页应用系统\n\n![单页富应用范例](http://nej.netease.com/images/sample.gif)\n\n从上图不难看出整个系统包含以下几部分内容：\n\n* 日志管理\n\n  * 日志：日志列表，可切换收件箱/草稿箱/回收站/标签\n  * 标签：标签列表，可转至日志按标签查看列表\n\n* 博客设置\n\n  * 账号管理\n\n    * 基本资料：用户基本资料设置表单\n    * 个人经历：个人经历填写表单\n\n  * 权限设置：权限设置表单\n\n而这些模块之间的层级关系则如下所示\n\n![模块层级结构图](http://img0.ph.126.net/7ixXaTU-uFtbe0pKCWCgPA==/6597270977286264717.png)\n\n针对交互式系统的这种层级架构典型的模式可以参阅[PAC（Presentation－Abstraction－Control）模式](http://en.wikipedia.org/wiki/Presentation%E2%80%93abstraction%E2%80%93control) 或者 [HMVC（Hierarchical model–view–controller）模式](http://en.wikipedia.org/wiki/Hierarchical_model%E2%80%93view%E2%80%93controller)\n\n然而在WEB交互式系统的实践过程中我们发现这种模式会存在一些缺陷：\n\n* 由于每个父模块自己维护了所有的子模块，因此父子模块之间耦合性过强，父模块必须耦合所有子模块\n* 由于模块之间不能直接越级调用，因此子模块需要其他模块协助时必须层层向上传递事件，如果层级过深则会影响到系统效率\n* 模块的增删等变化导致的变更涉及的影响较大，删除中间节点上的模块可能导致相邻的若干模块的变更\n* 多人协作开发系统时存在依赖关系的模块会导致开发人员之间的紧密耦合\n\n在这里我们给出了一种基于模块标识的依赖管理配置方案，可以彻底的将模块进行解耦，每个模块可以独立完整的完成自己的交互功能，而系统的整合则可以通过配置的方式灵活的重组各模块，模块的增删操作只需修改配置即可完成，而无需影响到具体业务逻辑\n\n下文我们会通过以上例子来讲解此方案的原理和实际操作方式\n\n#### 模块标识\n\n因为本方案会基于模块标识做配置，因此在介绍方案之前我们先介绍一下模块标识，这里我们给模块标识取名为**UMI**（Uniform Module Identifier）统一模块标识，下文简称UMI，遵循以下规则约定\n\n* 格式同URI的Path部分，如 /m/m0/\n* 必须以“/”符开始\n* 私有模块必须以“/?”开始\n* 承载模块的依赖关系，如 /m/m0/ 和 /m/m1/ 表明这两个标识对应模块的父模块标识均为 /m\n\n每个UMI均可唯一标识一个模块及模块在系统中的依赖关系，在模块章节我们介绍了一个模块可以用一个html进行封装，因此我们可以得到以下结果\n\n![UMI与模块地址映射关系图](http://img0.ph.126.net/DCSPjxzVgjlgc8B983YSSg==/2673167853921558567.png)\n\n每个UMI均可映射到一个模块实现文件，这样我们就可以将模块从具体实现中解耦出来，对模块的增删修改操作只需调整UMI和模块文件的映射关系即可，而无需涉及具体业务逻辑的修改\n\n#### 模块依赖\n\n在解决了模块与实现分离的问题后，我们接下来需要将层级式的模块扁平化来解耦模块之间的依赖关系\n\n回到前面的例子，模块之间的层级关系如下图所示\n\n![模块层级关系图](http://img1.ph.126.net/NFbfUjokCb1KsI8tCj04xw==/6608203421400487879.jpg)\n\n如果我们将图中的依赖关系进行抽象分离后可以发现所有的模块即可呈现扁平的状态\n\n![模块关系分离图](http://img1.ph.126.net/XByNuSHTyJ_OzmAFIcqGKQ==/6608480498329578217.png)\n\n而对于模块之前的依赖关系的管理在所有系统中都是一致的，但是每个模块的具体功能实现是由系统来决定的，不同的系统是截然不同的，因此本方案提供的解决方案主要是用来维护模块之间的依赖关系的\n\n从上图我们可以比较清楚的看到模块之间的依赖关系呈现树状结构，因此我们会以树的结构来组织维护模块之间的依赖关系，我们称之为依赖关系树，而当我们将这棵树上的任意节点与根节点之间的路径用“/”分隔序列化后发现刚好与我们提供的UMI是匹配的，因此组成系统的模块的UMI可以跟依赖关系树的节点一一对应起来，如下图所示\n\n![依赖关系树节点序列化成UMI](http://img2.ph.126.net/cu36voh3bRXFx530aW6nkg==/6608921402492317376.png)\n\n在模块标识章节我们介绍了UMI与模块封装文件可以相互映射，因此依赖关系树上的节点可以直接与模块的实现文件做一一对应，如下图所示\n\n![依赖关系树映射模块实现文件](http://img1.ph.126.net/6Pfkz1_4dd32jnL60QQ1Kw==/6608598146073751639.png)\n\n至此，我们将垂直层级依赖的模块通过依赖关系树分解成了无任何关系的扁平模块结构\n\n#### 模块组合\n\n模块只需要有个呈现容器即可渲染出来，因此模块如果需要能够做任意组合，只需将模块分成两种类型：提供容器的模块和使用容器的模块即可，当然一个模块可同时兼具提供容器和使用容器的功能，提供容器的模块和使用容器的模块可任意组合\n\n![模块组合](http://img2.ph.126.net/D446SK2cBk_aGZFLVRwIew==/3669307796500606643.png)\n\n对于模块组合的配置代码范例\n\n```javascript\n'/m/blog/list/':{\n    module:'module/layout/blog.list/index.html',\n    composite:{\n        box:'/?/blog/box/',\n        tag:'/?/blog/tag/',\n        list:'/?/blog/list/',\n        clazz:'/?/blog/class/'\n    }\n}\n```\n\n### 调度策略\n\n在将模块扁平化后，各模块就可以安排给不同的开发人员进行功能实现和测试了，各模块完成后根据依赖关系树进行系统整合，系统整合后各模块会遵循一定的调度策略进行调度\n\n#### 模块状态\n\n根据模块调度的阶段划分，模块的状态可以分为以下四种：\n\n* 模块构建：构建模块结构\n* 模块显示：将模块渲染到指定的容器中\n* 模块刷新：根据外界输入的参数信息获取数据并展示（这里主要做数据处理）\n* 模块隐藏：模块放至内存中，回收由显示和刷新阶段产生的额外数据及结构\n\n调度策略主要控制模块在这几个阶段之间的转换规则\n\n#### 模块显示\n\n当用户请求显示一个模块时各模块会遵循以下步骤进行调度，假设请求显示 /m/blog/list/ 模块\n\n![显示调度策略](http://img1.ph.126.net/ip4S9-mTCAH943VGwXZ1OQ==/6619563575537201227.png)\n\n1. 检查目标节点到根节点路径上注册的模块，如果注册的是模块的实现文件地址，则请求载入模块实现文件\n2. 如果节点所在的模块的所有祖先节点已显示，则当前模块可被显示出来，否则等待祖先模块的显示调度\n3. 模块载入后根据第二步骤原则尝试调度目标模块的显示\n\n#### 模块切换\n\n当用户从一个模块切换到另外一个模块时各模块遵循以下步骤调度，假设从 /m/blog/list/ 切换到 /m/setting/account/edu/ 模块\n\n![模块切换](http://img0.ph.126.net/ca9IdYk2ezLL-zN8vRqI4Q==/6619574570653479153.png)\n\n1. 查找源模块与目标模块的公共父节点\n\n   ![查找公共模块](http://img2.ph.126.net/G36CYcFsck1w8Uf0k7oOIw==/6608672912864439374.png)\n\n2. 从源节点到公共节点之间的模块调度隐藏操作\n\n   ![隐藏模块](http://img0.ph.126.net/kCydlPd-q7yUIQ2rc65Eyg==/6608818048399307052.png)\n\n3. 从根节点到公共节点之间的模块调度刷新操作\n\n   ![刷新模块](http://img2.ph.126.net/sN7NPW5etJ0FVjv-TyBL9w==/6608677310910950450.png)\n\n4. 从公共节点到目标节点之间的模块调度显示操作\n\n   ![显示模块](http://img1.ph.126.net/DwnLyinZy9ZG8IX_uwOmsg==/6599306173308730570.png)\n\n### 消息通道\n\n大部分时候我们不建议使用模块之前的消息通信，实践中也存在一些特殊情况会需要模块之前的消息通信，这里提供两种方式的消息通讯\n\n* 点对点的消息：一个模块发送消息时明确指定目标模块的UMI\n* 观察订阅消息：一个模块可以对外申明发布了什么样的消息，有需要的模块可以订阅该模块UMI上的消息\n\n### 实例分析\n\n[NEJ框架](https://github.com/NetEaseWD/NEJ)根据以上描述对此套架构模式做了实现，我们用上面的具体实例讲解如何使用NEJ中的模块调度系统来拆分一个复杂系统、开发测试模块、整合系统等\n\n#### 系统分解\n\n##### 绘制层级关系图\n\n当我们拿到一个复杂系统时根据交互稿可以绘制出组成系统的模块的层级关系图，并确定系统对外可访问的模块\n\n![模块层级关系图](http://img1.ph.126.net/UmNMLNzb-Vjdtv8skT8kqg==/6608742182096989774.png)\n\n##### 抽象依赖关系树\n\n从模块的层级关系图中我们可以非常方便的抽象出模块的依赖关系树\n\n![抽象依赖关系树](http://img1.ph.126.net/BK5_LhDhh01addpDJuY4Yw==/6619331578583739475.png)\n\n将抽象出来的依赖关系树根据UMI规则进行格式化，格式化的主要操作包括\n\n* 增加一个名称为“/”的根结点（也可将“m”结点改为“/”）\n* 每个结点增加“/”的子节点作为默认节点\n\n![格式化依赖关系树](http://img2.ph.126.net/5b3ByaubY0XFOlnU1PZHAw==/6619382156118617138.png)\n\n至此输出的依赖关系树，具有以下特性：\n\n* 任何一个结点（除根结点外）到根结点路径上的结点名称用“/”分隔组合起来即为结点的UMI值，如list结点的UMI值为/m/blog/list\n* 任何结点上的模块都依赖于他祖先结点（注册有模块）上的模块存在，如blog结点和list结点均注册有模块，则list结点上的模块显示必须以blog结点上的模块的显示为先决条件\n\n##### 确定对外模块注册节点\n\n五个对外可访问的模块：日志、标签、基本资料、个人经历、权限设置，在依赖关系树中找到合适的结点（叶子结点，层级关系树在依赖关系树中对应的结点或“/”结点）来注册对外可访问的模块\n\n![对外模块注册节点](http://img0.ph.126.net/vC28JzPSddgzZdpEAeBZ2w==/6619485510211628655.png)\n\n##### 确定布局模块注册节点\n\n从可访问模块注册的结点往根结点遍历，凡碰到两模块交叉的结点即为布局模块注册结点，系统所需的组件相关的模块可注册到根结点，这样任何模块使用的时候都可以保证这些组件已经被载入\n\n![布局模块注册节点](http://img1.ph.126.net/Jjp0GCDfh2eXvaxJvhiCeQ==/6619215030351195733.png)\n\n##### 映射模块功能\n\n原则：结点的公共父结点实现结点上注册的模块的公共功能\n\n举例：blog结点和setting结点的公共父结点为m结点，则我们可以通过切换blog模块和setting模块识别不变的功能即为m模块实现的功能，同理其他模块\n\n![功能映射](http://img2.ph.126.net/64xhHIfGy4qdQKSV5Bym-g==/2679360303409193237.png)\n\n##### 分解复杂模块\n\n进一步分解复杂模块，一般需要分解的模块包括：\n\n* 可共用模块，比如日志列表，可以在日志管理页面呈现，也可以在弹层中显示\n* 逻辑上无必然联系的模块，如日志模块中日志列表与右侧的按标签查看的标签列表之间没有必然的联系，任何一个模块的移除或添加都不会影响到另外一个模块的业务逻辑\n\n![分解复杂模块](http://img1.ph.126.net/wRM1uAxQDRFhfAzlNw8b5Q==/6599274287471525959.png)\n\n至此我们可以得到两棵系统分解后的依赖关系树\n\n对外模块依赖关系树\n\n![对外模块依赖关系树](http://img2.ph.126.net/6yAKfH-sST3-RGc0xIxU2g==/6608788361585356880.png)\n\n私有模块依赖关系树\n\n![私有模块依赖关系树](http://img1.ph.126.net/KgimU46Zn4ZnUtxiBrXdKw==/6608191326772584502.png)\n\n##### 绘制模块功能规范表\n\n本例中为了说明分解过程将所有可分解的模块都做了分解，实际项目看具体情况，比如这里的/m模块组合的/?/tab/模块的功能可以直接在/m模块中实现，而不需要新建一个/?/tab/模块来实现这个功能\n\n规范表范例如下所示\n\n![功能规范表](http://img1.ph.126.net/e_0ZFwbefuXT5bZ6bq17Rg==/1496320976294650210.png)\n\n#### 构建目录\n\n##### 项目目录\n\n项目目录的构建如下图所示\n\n![项目目录](http://img0.ph.126.net/7mfjeInfGILw-tWQznxxLA==/6608777366469080397.png)\n\n各目录说明\n\n```\nwebroot                    项目前端开发相关目录\n   |- res                  静态资源文件目录，打包时可配置使用到该目录下的静态资源带版本信息\n   |- src                  前端源码目录，最终发布时该目录不会部署到线上\n       |- html\n            |- module      单页面模块目录，系统所有模块的实现均在此目录下\n            |- app.html    单页面入口文件\n```\n\n##### 模块单元目录\n\n根据模块封装规则一个模块单元由以下几部分组成：\n\n* 模块测试：模块实现的功能可以通过模块测试页面独立进行测试\n* 模块结构：模块所涉及的结构分解出来的若干模板集合\n* 模块逻辑：根据模块规范实现的模块业务逻辑，从模块基类继承\n* 模块样式：模块特有的样式，一般情况下这部分样式可以直接在css目录下实现\n\n结构范例如下所示\n\n![模块单元目录](http://img0.ph.126.net/o6dTV8RpqAtS63zxdz8sEg==/6608917004445806742.png)\n\n至此我们可以得到所有模块的目录结构如下所示\n\n![模块目录结构](http://img0.ph.126.net/2cMlaKsMBzOfAPPdH9IzkA==/6608797157678379135.png)\n\n#### 模块实现\n\n##### 结构\n\n这里我们假设系统的静态页面已经做完，这里的模块实现只是在原有结构的基础上进行结构分解和业务逻辑的实现，结构部分内容主要将模块相关的静态结构拆分成若干NEJ的模板，注意：\n\n* 模板中的外联资源如css，js文件地址如果使用的是相对路径则均相对于模块的html文件路径\n* 模板集合中的外联资源必须使用@TEMPLATE标记标识，这个在后面打包发布章节会详细介绍\n\nNEJ模板说明\n\n![NEJ模板](http://img2.ph.126.net/W_RhwYyx4kbPPGMpcVoUwQ==/6608414527633039667.png)\n\n模块结构举例\n\n```html\n<meta charset=\"utf-8\"/>\n\n<textarea name=\"txt\" id=\"m-ifrm-module\">\n  <div class=\"n-login\">\n    <div class=\"iner j-flag\">\n      <span class=\"cls j-flag\">×</span>\n      <span class=\"min j-flag\">－</span>\n    </div>\n    <div class=\"cnt j-cnt\"></div>\n  </div>\n</textarea>\n\n\n<textarea name=\"js\" data-src=\"./index.css\"></textarea>\n<textarea name=\"js\" data-src=\"./index.js\"></textarea>\n\n```\n\n##### 逻辑\n\n依赖util/dispatcher/module模块，从_$$ModuleAbstract扩展一个项目的模块基类，完成项目中模块特有属性、行为的抽象\n\n```javascript\n/*\n * ------------------------------------------\n * 项目模块基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/klass',\n    'util/dispatcher/module'\n],function(_k,_t,_p){\n    // variable declaration\n    var _pro;\n    /**\n     * 项目模块基类对象\n     * @class   {_$$Module}\n     * @extends {_$$ModuleAbstract}\n     * @param   {Object}  可选配置参数，已处理参数列表如下所示\n     */\n    _p._$$Module = _k._$klass();\n    _pro = _p._$$Module._$extend(_t._$$ModuleAbstract);\n    /**\n     * 操作\n     * @param  {Object}\n     * @return {Void}\n     */\n    _pro.__doSomething = function(_args){\n        // TODO\n    };\n\n    // TODO\n\n    return _p;\n});\n```\n\n根据模块状态的划分，我们在实现一个模块时需要实现以下几个接口\n\n![模块各阶段接口](http://img0.ph.126.net/8XyKVwG3dzG0dK59qteZFw==/6619467918025585071.png)\n\n各阶段对应的接口：\n\n* 构建 - \\_\\_doBuild：构建模块结构，缓存模块需要使用的节点，初始化组合控件的配置参数\n* 显示 - \\_\\_onShow：将模块放置到指定的容器中，分配组合控件，添加相关事件，执行\\_\\_onRefresh的业务逻辑\n* 刷新 - \\_\\_onRefresh：根据外界输入的参数信息获取数据并展示（这里主要做数据处理）\n* 隐藏 - \\_\\_onHide：模块放至内存中，回收在\\_\\_onShow中分配的组合控件和添加的事件，回收\\_\\_onRefresh中产生的视图（这里尽量保证执行完成后恢复到\\_\\_doBuild后的状态）\n\n具体模块实现举例\n\n```javascript\n/*\n * ------------------------------------------\n * 项目模块实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/klass',\n    'util/dispatcher/module',\n    '/path/to/project/module.js'\n],function(_k,_e,_t,_p){\n    // variable declaration\n    var _pro;\n    /**\n     * 项目模块对象\n     * @class   {_$$ModuleDemo}\n     * @extends {_$$Module}\n     * @param   {Object} 可选配置参数\n     */\n    _p._$$ModuleDemo = _k._$klass();\n    _pro = _p._$$ModuleDemo._$extend(_t._$$Module);\n    /**\n     * 构建模块，主要处理以下业务逻辑\n     * - 构建模块结构\n     * - 缓存后续需要使用的节点\n     * - 初始化需要使用的组件的配置信息\n     * @return {Void}\n     */\n    _pro.__doBuild = function(){\n        this.__super();\n        // TODO\n    };\n    /**\n     * 显示模块，主要处理以下业务逻辑\n     * - 添加事件\n     * - 分配组件\n     * - 处理输入信息\n     * @param  {Object} 输入参数\n     * @return {Void}\n     */\n    _pro.__onShow = function(_options){\n        this.__super(_options);\n        // TODO\n    };\n    /**\n     * 刷新模块，主要处理以下业务逻辑\n     * - 分配组件，分配之前需验证\n     * - 处理输入信息\n     * - 同步状态\n     * - 载入数据\n     * @return {Void}\n     */\n    _pro.__onRefresh = function(_options){\n        this.__super(_options);\n        // TODO\n    };\n    /**\n     * 隐藏模块，主要处理以下业务逻辑\n     * - 回收事件\n     * - 回收组件\n     * - 尽量保证恢复到构建时的状态\n     * @return {Void}\n     */\n    _pro.__onHide = function(){\n        this.__super();\n        // TODO\n    };\n    // notify dispatcher\n    _e._$regist(\n        'umi_or_alias',\n        _p._$$ModuleDemo\n    );\n\n    return _p;\n});\n```\n\n##### 消息\n\n###### 点对点消息\n\n模块可以通过\\_\\_doSendMessage接口向指定UMI的模块发送消息，也可以通过实现\\_\\_onMessage接口来接收其他模块发给他的消息\n\n发送消息\n\n```javascript\n_pro.__doSomething = function(){\n\n    // TODO\n\n    this.__doSendMessage(\n        '/m/setting/account/',{\n            a:'aaaaaa',\n            b:'bbbbbbbbb'\n        }\n    );\n};\n```\n\n接收消息\n\n```javascript\n_pro.__onMessage = function(_event){\n    // _event.from 消息来源\n    // _event.data 消息数据，这里可能是 {a:'aaaaaa',b:'bbbbbbbbb'}\n\n    // TODO\n};\n```\n\n###### 发布订阅消息\n\n发布消息\n\n```javascript\n_pro.__doSomething = function(){\n\n    // TODO\n\n    this.__doPublishMessage(\n        'onok',{\n            a:'aaaaaa',\n            b:'bbbbbbbb'\n        }\n    );\n};\n```\n\n订阅消息\n\n```javascript\n_pro.__doBuild = function(){\n\n    // TODO\n\n    this.__doSubscribeMessage(\n        '/m/message/account/','onok',\n        this.__onMessageReceive._$bind(this)\n    );\n};\n```\n\n##### 自测\n\n创建html页面，使用模板引入模块实现文件\n\n```html\n<!-- template box -->\n<div id=\"template-box\" style=\"display:none;\">\n  <textarea name=\"html\" data-src=\"../index.html\"></textarea>\n</div>\n```\n\n模块放至document.mbody指定的容器中\n\n```javascript\nNEJ.define([\n    'util/dispatcher/test'\n],function(_e){\n    document.mbody = 'module-id-0';\n    // test module\n    _e._$testByTemplate('template-box');\n});\n```\n\n#### 系统整合\n\n##### 映射依赖关系树\n\n系统整合时，我们只需要将依赖关系树中需要注册模块的节点同模块实现文件进行映射即可\n\n对外模块整合\n\n![对外模块整合](http://img2.ph.126.net/CQe6y5Bdgkl4bA5VsSIwzA==/6608893914701623469.png)\n\n私有模块整合\n\n![私有模块整合](http://img0.ph.126.net/upKrOu1fEmK_Q6x2jc-ibA==/6619430534630239416.png)\n\n##### 提取系统配置信息\n\n规则配置举例\n\n```javascript\n  rules:{\n      rewrite:{\n          '404':'/m/blog/list/',\n          '/m/blog/list/':'/m/blog/',\n          '/m/setting/account/':'/m/setting/'\n      },\n      title:{\n          '/m/blog/tag/':'日志标签',\n          '/m/blog/list/':'日志列表',\n          '/m/setting/permission/':'权限管理',\n          '/m/setting/account/':'基本资料',\n          '/m/setting/account/edu/':'教育经历'\n      },\n      alias:{\n          'system-tab':'/?/tab/',\n          'blog-tab':'/?/blog/tab/',\n          'blog-list-box':'/?/blog/box/',\n          'blog-list-tag':'/?/blog/tag/',\n          'blog-list-class':'/?/blog/class/',\n          'blog-list':'/?/blog/list/',\n          'setting-tab':'/?/setting/tab/',\n          'setting-account-tab':'/?/setting/account/tab/',\n\n          'layout-system':'/m',\n          'layout-blog':'/m/blog',\n          'layout-blog-list':'/m/blog/list/',\n          'layout-setting':'/m/setting',\n          'layout-setting-account':'/m/setting/account',\n\n          'blog-tag':'/m/blog/tag/',\n          'setting-edu':'/m/setting/account/edu/',\n          'setting-profile':'/m/setting/account/',\n          'setting-permission':'/m/setting/permission/'\n      }\n  }\n```\n\n模块配置举例\n\n```javascript\n  modules:{\n      '/?/tab/':'module/tab/index.html',\n      '/?/blog/tab/':'module/blog/tab/index.html',\n      '/?/blog/box/':'module/blog/list.box/index.html',\n      '/?/blog/tag/':'module/blog/list.tag/index.html',\n      '/?/blog/class/':'module/blog/list.class/index.html',\n      '/?/blog/list/':'module/blog/list/index.html',\n      '/?/setting/tab/':'module/setting/tab/index.html',\n      '/?/setting/account/tab/':'module/setting/account.tab/index.html',\n\n      '/m':{\n          module:'module/layout/system/index.html',\n          composite:{\n              tab:'/?/tab/'\n          }\n      },\n      '/m/blog':{\n          module:'module/layout/blog/index.html',\n          composite:{\n              tab:'/?/blog/tab/'\n          }\n      },\n      '/m/blog/list/':{\n          module:'module/layout/blog.list/index.html',\n          composite:{\n              box:'/?/blog/box/',\n              tag:'/?/blog/tag/',\n              list:'/?/blog/list/',\n              clazz:'/?/blog/class/'\n          }\n      },\n      '/m/blog/tag/':'module/blog/tag/index.html',\n\n      '/m/setting':{\n          module:'module/layout/setting/index.html',\n          composite:{\n              tab:'/?/setting/tab/'\n          }\n      },\n      '/m/setting/account':{\n          module:'module/layout/setting.account/index.html',\n          composite:{\n              tab:'/?/setting/account/tab/'\n          }\n      },\n      '/m/setting/account/':'module/setting/profile/index.html',\n      '/m/setting/account/edu/':'module/setting/edu/index.html',\n      '/m/setting/permission/':'module/setting/permission/index.html'\n  }\n```\n\n##### 模块组合\n\n模块通过__export属性开放组合模块的容器，__export中的parent为子模块的容器节点，顶层模块（如 “/m”）可以通过重写__doParseParent来明确指定应用所在容器\n\n```javascript\n_pro.__doBuild = function(){\n    this.__body = _e._$html2node(\n        _e._$getTextTemplate('module-id-l2')\n    );\n    // 0 - box select\n    // 1 - class list box\n    // 2 - tag list box\n    // 3 - sub module box\n    var _list = _e._$getByClassName(this.__body,'j-flag');\n    this.__export = {\n        box:_list[0],\n        clazz:_list[1],\n        tag:_list[2],\n        list:_list[3],\n        parent:_list[3]\n    };\n};\n```\n\n通过composite配置模块组合\n\n```javascript\n'/m/blog/list/':{\n    module:'module/layout/blog.list/index.html',\n    composite:{\n        box:'/?/blog/box/',\n        tag:'/?/blog/tag/',\n        list:'/?/blog/list/',\n        clazz:'/?/blog/class/'\n    }\n}\n```\n\n模块组合时可以指定组合模块的处理状态\n* onshow  - 这里配置的组合模块仅在模块显示时组合，后续的模块refresh操作不会导致组合模块的refresh，适合于模块在显示后不会随外界输入变化而变化的模块\n* onrefresh  -  这里配置的模块在模块显示时组合，后续如果模块refresh时也会跟随做refresh操作，适用于组合的模块需要与外部输入同步的模块\n* 不指定onshow或者onrefresh的模块等价于onrefresh配置的模块\n\n```javascript\ncomposite:{\n    onshow:{\n        // 模块onshow时组合\n        // 组合的模块在模块onrefresh时不会刷新\n    },\n    onrefresh{\n        // 模块onshow时组合\n        // 组合的模块在模块onrefresh时也同时会刷新\n    }\n    // 这里配置的组合模块等价于onrefresh中配置的模块\n}\n```\n\n##### 启动应用\n\n根据配置启动应用\n\n```javascript\nNEJ.define([\n    'util/dispatcher/dispatcher'\n],function(_e){\n    _e._$startup({\n        // 规则配置\n        rules:{\n            rewrite:{\n                // 重写规则配置\n            },\n            title:{\n                // 标题配置\n            },\n            alias:{\n                // 别名配置\n                // 建议模块实现文件中的注册采用这里配置的别名\n            }\n        },\n        // 模块配置\n        modules:{\n            // 模块UMI对应实现文件的映射表\n            // 同时完成模块的组合\n        }\n    });\n});\n```\n\n#### 打包发布\n\n打包发布内容详见[NEJ工具集](https://github.com/genify/toolkit)相关文档\n\n### 系统变更\n\n当系统需求变化而进行模块变更我们只需要开发新的模块或删除模块配置即可\n\n#### 新增模块\n\n如果增加一个全新的模块则只需按照上面的逻辑实现步骤开发一个模块即可\n\n如果新增的模块功能在系统中已经实现，则只需修改配置即可，如上例中我们需要在将日志管理下的标签模块在博客设置中也加一份，访问路径为/m/setting/tag/\n\n![新增模块](http://img0.ph.126.net/s4pv6FZmPal8Jx0m0eNltA==/6619471216560468933.png)\n\n修改规则配置\n\n```javascript\nrules:{\n    // ...\n    alias:{\n        // ...\n        'blog-tag':['/m/blog/tag/','/m/setting/tag/']\n    }\n}\n```\n\n修改模块配置\n\n```javascript\nmodules:{\n    // ...\n    '/m/setting/tag/':'module/blog/tag/index.html'\n}\n```\n\n如果要在/?/setting/tab模块的结构模板中增加一个标签即可\n\n```html\n<textarea name=\"txt\" id=\"module-id-8\">\n  <div class=\"ma-t w-tab f-cb\">\n    <a class=\"itm fl\" href=\"#/setting/account/\" data-id=\"/setting/account/\">账号管理</a>\n    <a class=\"itm fl\" href=\"#/setting/permission/\" data-id=\"/setting/permission/\">权限设置</a>\n    <a class=\"itm fl\" href=\"#/setting/tag/\" data-id=\"/setting/tag/\">日志标签</a>\n  </div>\n</textarea>\n```\n\n#### 删除模块\n\n将退化的模块从系统中删除只需要将模块对应的UMI配置从模块配置中删除即可，而无需修改具体业务逻辑\n\n\n"
  },
  {
    "path": "doc/guide/Build.Scalable.Web.System/Platform.md",
    "content": "# 构建高可伸缩性的WEB交互式系统(1) - 平台的可伸缩性\n\n## 概述\n\n可伸缩性是一种对软件系统处理能力的设计指标，高可伸缩性代表一种弹性，在系统扩展过程中，能够保证旺盛的生命力，通过很少的改动，就能实现整个系统处理能力的增长。\n\n在系统设计的时候，充分地考虑系统的可伸缩性，一方面能够极大地减少日后的维护开销，并帮助决策者对于投资所能获得的回报进行更加精准的估计；另一方面，高可伸缩性的系统往往会具有更好的容灾能力，从而提供更好的用户体验。\n\nWEB交互式系统的可伸缩性主要体现在两个方面：\n\n* 平台的可伸缩性：随着WEB技术的发展，越来越多的平台开始使用WEB技术来构建系统，一方面不同的平台提供的环境支持存在着各种差异；另一方面随着平台的发展，不断的会有一些旧平台退出历史舞台，新平台转而成为主流平台；因此构建的WEB系统需要能够快速的响应此类变化就需要其具备良好的平台伸缩性\n* 模块的可伸缩性：随着系统功能不断增删更新需求的变化，系统可能会变得越来越复杂，冗余信息也可能会越来越多，改动所带来的影响范围也可能会越来越大，因此良好的模块伸缩性可保证系统具有良好的可维护性，让系统始终处于最佳状态\n\nWEB交互式系统的主要应用包括：\n\n* 桌面端/移动端网站类系统（如 [网易云课堂](http://study.163.com/)、[Lofter移动WEB版](http://www.lofter.com/)等）\n* 移动混合应用（如 [网易云相册IPad版](http://photo.163.com/cloudphotos/)、[Lofter](http://www.lofter.com/app)等）\n* 桌面混合应用（如 [网易云音乐PC版](http://music.163.com/#/download)、[网易邮箱助手](http://mailease.163.com/)等）\n\n## 平台的可伸缩性\n\nWEB交互式系统对平台的可伸缩性主要表现为：\n\n* 可扩展性：对于新兴平台能够快速进行支持\n* 可缩减性：对于过时的平台冗余信息能够以最小的修改方式剔除\n\n首先我们先介绍一下WEB交互式系统的目标平台的情况\n\n### 平台分类\n\n根据系统所在容器的差异将平台分为浏览器平台和混合应用平台两大类，各分类的详细说明见下文所述\n\n#### 浏览器平台\n\n##### 按引擎划分\n\n浏览器平台按照主流引擎可以划分为以下几类：\n\n![按引擎划分平台](http://img0.ph.126.net/gmJEDK7pAdfE8nH4VQexkA==/6608273790144412074.png)\n\n| 引擎 | 说明 |\n| :--- | :--- |\n| Trident | 由微软研发的排版引擎，代表浏览器有Internet Explorer |\n| Webkit  | 由Apple、Google、Adobe等公司推动的开源的排版引擎，代表浏览器有Apple Safari、Google Chrome |\n| Gecko   | 由Mozilla基金会支持的开源排版引擎，代表浏览器有Mozilla Firefox |\n| Presto  | 由Opera Software研发的商用排版引擎，代表浏览器有Opera，由于Opera从15以后就开始采用新的Blink引擎，因此Presto也将逐步淡出我们的目标平台 |\n| Blink   | 由Google和Opera Software基于Webkit引擎研发的排版引擎，代表浏览器有Chrome 28+、Opera 15+ |\n\n##### 按功能划分\n\n各引擎的浏览器版本根据对标准、规范的支持程度进行划分可分为以下几类：\n\n![按功能划分平台](http://img1.ph.126.net/PELRvZvw_Gx7DTN3v7hUFQ==/6608921402492080696.png)\n\n由于目前国内基于Trident的Internet Explorer浏览器还占有大量的市场份额，包括低版本的Internet Explorer浏览器，因此我们将浏览器分成三个等级\n\n| 标准性 | 说明 |\n| :--- | :--- |\n| 差 | 主要针对低版本的Trident引擎（如IE6浏览器）平台，这部分平台对规范和标准的支持程度比较差，在适配时需要做大量额外的适配工作来实现相应的功能，因此如果产品的目标平台定位需要支持此平台则会有一定的性能损耗 |\n| 中 | 主要针对中间版本的Trident引擎（如IE7-9浏览器）平台，这部分平台对规范和标准有一定的支持，但是也存在若干功能需要做额外的适配工作来实现 |\n| 好 | 主要针对对规范、标准支持比较好的平台，按照标准实现的功能无需做额外的适配工作，因此如果产品的目标平台定位为此平台将取得比较好的用户体验和性能，如移动产品、混合应用等 |\n\n#### 混合应用平台\n\n根据混合应用的宿主平台的差异我们将混合应用的目标平台分为以下几类：\n\n![混合平台划分](http://img1.ph.126.net/1VV98yGBpj3E2KPaa9M3jg==/6608853232771155778.png)\n\n| 宿主     | 说明 |\n| :---     | :--- |\n| Android  | Android系统的混合应用，浏览器引擎会自动适配至Webkit |\n| IOS      | IOS系统的混合应用，浏览器引擎会自动适配至Webkit |\n| WinPhone | Windows Phone系统的混合应用，浏览器引擎会自动适配至Trident |\n| PC       | 桌面应用，采用CEF做为容器，浏览器引擎会自动适配至Webkit |\n\n### 平台适配\n\nAOP(Aspect-Oriented Programming)：面向切面的编程范式，其核心思想是将横切关注点从主关注点中分离出来，因此特定领域的问题代码可以从标准业务逻辑中分离出来，从而使得主业务逻辑和领域性业务逻辑之间不会存在任何耦合性。\n\n这里我们可以借鉴AOP思想来实现平台的适配策略，结合不同的平台实现逻辑，我们可以认为对于使用规范、标准来实现业务逻辑的部分为我们的主关注点，而不同平台可以做为若干的切面关注点进行封装，各平台只需关注自己平台下对标准的修正逻辑即可，因此可以通过增加、删除平台修正的切面逻辑来实现对不同平台的适配。\n\n实现时我们首先提取标准业务逻辑，然后各平台根据实际情况实现对业务逻辑的修正\n\n![AOP策略](http://img2.ph.126.net/27YJvuHJvtvBFv4FoYX7QA==/6608822446445580374.png)\n\n* 标准业务逻辑：主关注点，这里主要是使用根据W3C、ES标准来实现的业务逻辑\n* 前置平台修正逻辑：领域特定关注点，主要是根据平台特性对标准在该平台下的修正，修正逻辑会先于标准逻辑执行\n* 后置平台修正逻辑：同前置平台修正逻辑，也是领域特定关注点，修正逻辑会在标准逻辑执行后再执行\n\n根据此思路我们对比以下两段代码：\n\n代码一：目前常用的平台适配方式\n\n```javascript\nfunction doSomething(){\n    if(isTrident){\n        // TODO trident implement\n    }else if(isWebkit){\n        // TODO webkit implement\n    }else if(isGecko){\n        // TODO gecko implement\n    }else if(isPresto){\n        // TODO presto implement\n    }else{\n        // TODO w3c implement\n    }\n}\n\n// 上层应用使用\ndoSomething(1,2,3);\n```\n\n此方式对所有平台的修正逻辑均在主逻辑中实现，存在以下弊端：\n\n* 对平台特有的修正逻辑耦合在主逻辑中，平台特有的更新必然引起主逻辑的更新\n* 对于新增或删除平台的支持必须修改到主业务逻辑\n* 无法分离不必要的平台修正，比如基于webkit引擎的移动平台应用不需要其他平台的修正逻辑\n\n代码二：借鉴AOP思想的平台适配方式\n\n```javascript\nfunction doSomething(){\n    // TODO w3c/es implement\n}\n\n// 上层应用使用\ndoSomething(1,2,3);\n```\n\n针对Trident平台适配的逻辑，比如 trident.js中\n\n```javascript\n// trident implement\ndoSomething = doSomething._$aop(\n    function(_event){\n        // TODO trident implement\n    },\n    function(_event){\n        // TODO trident implement\n    }\n);\n```\n\n对比代码一，我们可以发现借鉴AOP思想的接口适配方式分离了标准业务逻辑和平台特有业务逻辑，是否增加平台特有业务逻辑并不会影响主业务逻辑的执行，而对于平台修正逻辑的切入则可以直接通过配置的方式灵活的进行增删，因此我们可以从中得到以下好处：\n\n* 主逻辑和平台特有逻辑无耦合性，可随意分离、整合\n* 对于新增平台适配只需新加平台特有逻辑即可，而无需影响到主业务逻辑\n* 可通过配置控制支持的目标平台，有选择性的导出平台特有业务逻辑\n\n### 实现举例\n\n[NEJ框架](https://github.com/NetEaseWD/NEJ)借鉴AOP思想提供了配置式的平台适配系统，对于这部分的详细信息可参阅NEJ的《[依赖管理系统](../DEPENDENCY.md)》和《[平台适配系统](../PLATFORM.md)》了解更为详细的信息，以下选取其中相关原理部分进行举例说明\n\n#### platform\n\n控件依赖补丁名称为“platform”，只用于文件依赖，使用“{platform}xxx.js”来表示控件依赖的补丁文件，会解析为依赖xxx.js和xxx.patch.js两个文件。xxx.js为W3C/ES规范实现方式，提供所有标准平台支持的公用部分，xxx.patch.js通过NEJ.patch接口提供不同平台对这些接口的特有实现逻辑\n\n一个典型的适配控件结构如下图所示\n\n![适配控件结构](http://img1.ph.126.net/shaaEm3oj13JZcdMF9iHTQ==/6608208918958379461.png)\n\n这里的widget.js是控件业务逻辑实现文件，在此控件的实现中会依赖到存在平台差异的API，其依赖代码如下所示\n\n```javascript\nNEJ.define([\n    'util/event',\n    '{platform}api.js'\n],function(t,h,p){\n\n    // TODO\n\n});\n```\n\n这里对 {platform}api.js 的处理方式如下图所示，这里的./相对于当前的代码文件即widget.js文件所在的目录\n\n![platform](http://img2.ph.126.net/ygcxx2DAXf5YbpQ8No7SWg==/6608689405538619068.png)\n\n这里的api.js文件为需平他适配API的标准实现逻辑，而api.patch.js文件则利用NEJ.patch接口对各平台做按需适配逻辑，同时打包时也根据NEJ.patch接口中对平台的条件识别做按需输出，由于api.patch.js文件最终会按需输出，因此在此文件中除了使用NEJ.patch做平台适配逻辑外不允许包含其它业务逻辑\n\n#### NEJ.patch\n\nNEJ框架中的平台按需适配采用NEJ.patch接口来实现，由于打包发布后NEJ.patch相关的接口会被分离出来不会发布上线，因此仅允许在patch文件中调用此接口，平台引擎标识说明如下\n\n| 标识  | 说明 |\n| :---  | :--- |\n| T     | Trident引擎，如IE |\n| W     | Webkit引擎，如chrome |\n| G     | Gecko引擎，如firefox |\n\n内置的Trident引擎版本对应的IE版本关系\n\n| Trident版本 | IE版本 |\n| :---  | :--- |\n| 2.0 | 6 |\n| 3.0 | 7 |\n| 4.0 | 8 |\n| 5.0 | 9 |\n| 6.0 | 10 |\n| 7.0 | 11 |\n\n接口说明\n\n|      | 类型 | 描述 |\n| :--- | :--- | :--- |\n| 输入 | String   |   必须，平台的判断条件，如2=<TR<4 |\n|      | Array    | 可选，依赖文件列表，规则同define接口定义的文件路径 |\n|      | Function | 可选，当前条件下需要执行的脚本 |\n| 输出 | Void     | 无 |\n\n```javascript\n\n// 此文件只能定义NEJ.patch不可执行其他业务逻辑\n// 打包输出时仅根据平台配置输出所需处理逻辑\n// 实际情况看需求，可将平台相关部分逻辑独立到单独的模块中\n\nNEJ.define([\n    './hack.js'\n],function(h){\n    // 针对trident平台的处理逻辑\n    NEJ.patch('TR',function(){\n        // TODO\n    });\n\n    // 针对gecko平台的处理逻辑\n    NEJ.patch('GR',[\n        './hack.firefox.js'\n    ],function(fh){\n        // TODO\n    });\n\n    // 针对IE6平台的处理逻辑\n    NEJ.patch('TR==2.0',['./hack.ie6.js']);\n\n    // 针对IE7-IE9的处理逻辑\n    NEJ.patch('3.0<=TR<=5.0',function(){\n        // TODO\n    });\n\n    // 这里必须同hack.js文件的返回值一致\n    return h;\n});\n```\n\n#### 平台配置\n\n平台参数在开发及打包过程中都会使用，框架支持平台参数的配置通过define.js路径上查询串中的p参数输入。\n\n平台配置信息，此配置又分两类基本配置：补丁配置和混合配置，因为混合模式下使用的浏览器引擎固定，因此当配置中出现混合类型的配置时忽略补丁配置的值。\n\n如果在引入依赖定义库时未指定平台信息则表示系统需对全平台浏览器支持。\n\n##### 补丁配置\n\n主要用来修正浏览器平台对接口及控件的支持，按照目前浏览器引擎划分，参数值由一个或者多个平台标识组成，标识支持如下所示：\n\n| 标识  | 说明 |\n| :---  | :--- |\n| gk    | 以gecko为核心的浏览器平台，如firefox等 |\n| wk    | 以webkit为核心的浏览器平台，如chrome、safari等 |\n| td    | 以trident为核心的浏览器平台，如IE、360、maxthon等 |\n| td-0  | 以trident为核心的浏览器平台，且引擎内核版本大于等于3.0，即IE>=7 |\n| td-1  | 以trident为核心的浏览器平台，且引擎内核版本大于等于7.0，即IE>=10 |\n\n```html\n<script src=\"/path/to/nej/define.js?p=wk|gk|td\"></script>\n```\n\n##### 混合配置\n\n主要用于混合开发模式下对native接口的适配，按照native平台划分，参数值由一个标识组成，多个标识则以识别的第一个标识为准，标识支持如下所示：\n\n| 标识 | 说明 |\n| :--- | :--- |\n| cef       | 基于cef框架混合应用，主要针对桌面应用 |\n| ios       | ios平台混合应用，如iphone应用、ipod应用、ipad应用等 |\n| win       | windows phone平台混合应用 |\n| android   | android平台混合应用 |\n\n```html\n<script src=\"/path/to/nej/define.js?p=cef\"></script>\n```\n\n### 平台变更\n\n通过以上实现举例我们可以看到当平台发生变更时我们可以快速进行扩展或缩减\n\n#### 平台扩展\n\n当有新平台需要作为系统目标平台时，我们只需要做以下工作：\n\n* 增加平台配置识别符，如nxw\n* 识别该平台与标准存在的差异，增加平台特有业务逻辑至patch\n* 系统对平台配置部分增加新添的识别符，如\n\n    原平台适配\n    ```html\n    <script src=\"/path/to/nej/define.js?p=wk|gk|td\"></script>\n    ```\n\n    新增平台适配\n    ```html\n    <script src=\"/path/to/nej/define.js?p=wk|gk|td|nxw\"></script>\n    ```\n\n即可完成对平台的扩展，而不会影响到原有的业务逻辑\n\n#### 平台缩减\n\n当系统适配的目标平台由于某种原因退出历史舞台时，系统也需要将该平台的冗余代码从系统中剔除，我们只需要做以下工作：\n\n* 系统对平台配置部分删除要剔除的平台标识，如\n\n    原平台适配\n    ```html\n    <script src=\"/path/to/nej/define.js?p=wk|gk|td\"></script>\n    ```\n\n    缩减后平台适配\n    ```html\n    <script src=\"/path/to/nej/define.js?p=wk\"></script>\n    ```\n\n即可完成对平台的缩减，而无需修改任何业务逻辑\n\n\n"
  },
  {
    "path": "doc/guide/Build.Scalable.Web.System.md",
    "content": "# 构建高可伸缩性的WEB交互式系统\n\n## 概述\n\n可伸缩性是一种对软件系统处理能力的设计指标，高可伸缩性代表一种弹性，在系统扩展过程中，能够保证旺盛的生命力，通过很少的改动，就能实现整个系统处理能力的增长。\n\n在系统设计的时候，充分地考虑系统的可伸缩性，一方面能够极大地减少日后的维护开销，并帮助决策者对于投资所能获得的回报进行更加精准的估计；另一方面，高可伸缩性的系统往往会具有更好的容灾能力，从而提供更好的用户体验。\n\nWEB交互式系统的可伸缩性主要体现在两个方面：\n\n* 平台的可伸缩性：随着WEB技术的发展，越来越多的平台开始使用WEB技术来构建系统，一方面不同的平台提供的环境支持存在着各种差异；另一方面随着平台的发展，不断的会有一些旧平台退出历史舞台，新平台转而成为主流平台；因此构建的WEB系统需要能够快速的响应此类变化就需要其具备良好的平台伸缩性\n* 模块的可伸缩性：随着系统功能不断增删更新需求的变化，系统可能会变得越来越复杂，冗余信息也可能会越来越多，改动所带来的影响范围也可能会越来越大，因此良好的模块伸缩性可保证系统具有良好的可维护性，让系统始终处于最佳状态\n\nWEB交互式系统的主要应用包括：\n\n* 桌面端/移动端网站类系统（如 [网易云课堂](http://study.163.com/)、[易信WebIM](http://web.yixin.im/)、[Lofter移动WEB版](http://www.lofter.com/)等）\n* 移动混合应用（如 [网易云相册IPad版](http://photo.163.com/cloudphotos/)、[Lofter](http://www.lofter.com/app)等）\n* 桌面混合应用（如 [网易云音乐PC版](http://music.163.com/#/download)、[网易邮箱助手](http://mailease.163.com/)等）\n\n## 平台的可伸缩性\n\nWEB交互式系统对平台的可伸缩性主要表现为：\n\n* 可扩展性：对于新兴平台能够快速进行支持\n* 可缩减性：对于过时的平台冗余信息能够以最小的修改方式剔除\n\n首先我们先介绍一下WEB交互式系统的目标平台的情况\n\n### 平台分类\n\n根据系统所在容器的差异将平台分为浏览器平台和混合应用平台两大类，各分类的详细说明见下文所述\n\n#### 浏览器平台\n\n##### 按引擎划分\n\n浏览器平台按照主流引擎可以划分为以下几类：\n\n![按引擎划分平台](http://img0.ph.126.net/gmJEDK7pAdfE8nH4VQexkA==/6608273790144412074.png)\n\n| 引擎 | 说明 |\n| :--- | :--- |\n| Trident | 由微软研发的排版引擎，代表浏览器有Internet Explorer |\n| Webkit  | 由Apple、Google、Adobe等公司推动的开源的排版引擎，代表浏览器有Apple Safari、Google Chrome |\n| Gecko   | 由Mozilla基金会支持的开源排版引擎，代表浏览器有Mozilla Firefox |\n| Presto  | 由Opera Software研发的商用排版引擎，代表浏览器有Opera，由于Opera从15以后就开始采用新的Blink引擎，因此Presto也将逐步淡出我们的目标平台 |\n| Blink   | 由Google和Opera Software基于Webkit引擎研发的排版引擎，代表浏览器有Chrome 28+、Opera 15+ |\n\n##### 按功能划分\n\n各引擎的浏览器版本根据对标准、规范的支持程度进行划分可分为以下几类：\n\n![按功能划分平台](http://img1.ph.126.net/PELRvZvw_Gx7DTN3v7hUFQ==/6608921402492080696.png)\n\n由于目前国内基于Trident的Internet Explorer浏览器还占有大量的市场份额，包括低版本的Internet Explorer浏览器，因此我们将浏览器分成三个等级\n\n| 标准性 | 说明 |\n| :--- | :--- |\n| 差 | 主要针对低版本的Trident引擎（如IE6浏览器）平台，这部分平台对规范和标准的支持程度比较差，在适配时需要做大量额外的适配工作来实现相应的功能，因此如果产品的目标平台定位需要支持此平台则会有一定的性能损耗 |\n| 中 | 主要针对中间版本的Trident引擎（如IE7-9浏览器）平台，这部分平台对规范和标准有一定的支持，但是也存在若干功能需要做额外的适配工作来实现 |\n| 好 | 主要针对对规范、标准支持比较好的平台，按照标准实现的功能无需做额外的适配工作，因此如果产品的目标平台定位为此平台将取得比较好的用户体验和性能，如移动产品、混合应用等 |\n\n#### 混合应用平台\n\n根据混合应用的宿主平台的差异我们将混合应用的目标平台分为以下几类：\n\n![混合平台划分](http://img1.ph.126.net/1VV98yGBpj3E2KPaa9M3jg==/6608853232771155778.png)\n\n| 宿主     | 说明 |\n| :---     | :--- |\n| Android  | Android系统的混合应用，浏览器引擎会自动适配至Webkit |\n| IOS      | IOS系统的混合应用，浏览器引擎会自动适配至Webkit |\n| WinPhone | Windows Phone系统的混合应用，浏览器引擎会自动适配至Trident |\n| PC       | 桌面应用，采用CEF做为容器，浏览器引擎会自动适配至Webkit |\n\n### 平台适配\n\nAOP(Aspect-Oriented Programming)：面向切面的编程范式，其核心思想是将横切关注点从主关注点中分离出来，因此特定领域的问题代码可以从标准业务逻辑中分离出来，从而使得主业务逻辑和领域性业务逻辑之间不会存在任何耦合性。\n\n这里我们可以借鉴AOP思想来实现平台的适配策略，结合不同的平台实现逻辑，我们可以认为对于使用规范、标准来实现业务逻辑的部分为我们的主关注点，而不同平台可以做为若干的切面关注点进行封装，各平台只需关注自己平台下对标准的修正逻辑即可，因此可以通过增加、删除平台修正的切面逻辑来实现对不同平台的适配。\n\n实现时我们首先提取标准业务逻辑，然后各平台根据实际情况实现对业务逻辑的修正\n\n![AOP策略](http://img2.ph.126.net/27YJvuHJvtvBFv4FoYX7QA==/6608822446445580374.png)\n\n* 标准业务逻辑：主关注点，这里主要是使用根据W3C、ES标准来实现的业务逻辑\n* 前置平台修正逻辑：领域特定关注点，主要是根据平台特性对标准在该平台下的修正，修正逻辑会先于标准逻辑执行\n* 后置平台修正逻辑：同前置平台修正逻辑，也是领域特定关注点，修正逻辑会在标准逻辑执行后再执行\n\n根据此思路我们对比以下两段代码：\n\n代码一：目前常用的平台适配方式\n\n```javascript\nfunction doSomething(){\n    if(isTrident){\n        // TODO trident implement\n    }else if(isWebkit){\n        // TODO webkit implement\n    }else if(isGecko){\n        // TODO gecko implement\n    }else if(isPresto){\n        // TODO presto implement\n    }else{\n        // TODO w3c implement\n    }\n}\n\n// 上层应用使用\ndoSomething(1,2,3);\n```\n\n此方式对所有平台的修正逻辑均在主逻辑中实现，存在以下弊端：\n\n* 对平台特有的修正逻辑耦合在主逻辑中，平台特有的更新必然引起主逻辑的更新\n* 对于新增或删除平台的支持必须修改到主业务逻辑\n* 无法分离不必要的平台修正，比如基于webkit引擎的移动平台应用不需要其他平台的修正逻辑\n\n代码二：借鉴AOP思想的平台适配方式\n\n```javascript\nfunction doSomething(){\n    // TODO w3c/es implement\n}\n\n// 上层应用使用\ndoSomething(1,2,3);\n```\n\n针对Trident平台适配的逻辑，比如 trident.js中\n\n```javascript\n// trident implement\ndoSomething = doSomething._$aop(\n    function(_event){\n        // TODO trident implement\n    },\n    function(_event){\n        // TODO trident implement\n    }\n);\n```\n\n对比代码一，我们可以发现借鉴AOP思想的接口适配方式分离了标准业务逻辑和平台特有业务逻辑，是否增加平台特有业务逻辑并不会影响主业务逻辑的执行，而对于平台修正逻辑的切入则可以直接通过配置的方式灵活的进行增删，因此我们可以从中得到以下好处：\n\n* 主逻辑和平台特有逻辑无耦合性，可随意分离、整合\n* 对于新增平台适配只需新加平台特有逻辑即可，而无需影响到主业务逻辑\n* 可通过配置控制支持的目标平台，有选择性的导出平台特有业务逻辑\n\n### 实现举例\n\n[NEJ框架](https://github.com/NetEaseWD/NEJ)借鉴AOP思想提供了配置式的平台适配系统，对于这部分的详细信息可参阅NEJ的《[依赖管理系统](https://github.com/genify/nej/blob/master/doc/DEPENDENCY.md)》和《[平台适配系统](https://github.com/genify/nej/blob/master/doc/PLATFORM.md)》了解更为详细的信息，以下仅举例说明NEJ中适配的使用方式\n\n一个典型的适配控件结构如下图所示\n\n![适配控件结构](http://img1.ph.126.net/shaaEm3oj13JZcdMF9iHTQ==/6608208918958379461.png)\n\n这里的widget.js是控件业务逻辑实现文件，在此控件的实现中会依赖到存在平台差异的API，其依赖代码如下所示\n\n```javascript\nNEJ.define([\n    'util/event',\n    '{platform}api.js'\n],function(t,h,p){\n\n    // TODO\n\n});\n```\n\n这里对 {platform}api.js 的处理方式如下图所示，这里的./相对于当前的代码文件即widget.js文件所在的目录\n\n![platform](http://img2.ph.126.net/ygcxx2DAXf5YbpQ8No7SWg==/6608689405538619068.png)\n\n这里的api.js文件为需平他适配API的标准实现逻辑，而api.patch.js文件则利用NEJ.patch接口对各平台做按需适配逻辑，同时打包时也根据NEJ.patch接口中对平台的条件识别做按需输出，由于api.patch.js文件最终会按需输出，因此在此文件中除了使用NEJ.patch做平台适配逻辑外不允许包含其它业务逻辑\n\n```javascript\n\n// 此文件只能定义NEJ.patch不可执行其他业务逻辑\n// 打包输出时仅根据平台配置输出所需处理逻辑\n// 实际情况看需求，可将平台相关部分逻辑独立到单独的模块中\n\nNEJ.define([\n    './hack.js'\n],function(h){\n    // 针对trident平台的处理逻辑\n    NEJ.patch('TR',function(){\n        // TODO\n    });\n\n    // 针对gecko平台的处理逻辑\n    NEJ.patch('GR',[\n        './hack.firefox.js'\n    ],function(fh){\n        // TODO\n    });\n\n    // 针对IE6平台的处理逻辑\n    NEJ.patch('TR==2.0',['./hack.ie6.js']);\n\n    // 针对IE7-IE9的处理逻辑\n    NEJ.patch('3.0<=TR<=5.0',function(){\n        // TODO\n    });\n\n    // 这里必须同hack.js文件的返回值一致\n    return h;\n});\n```\n\n最后我们只需要配置产品的目标平台即可输出平台对应的适配，而不会存在其他平台的额外影响\n\n```html\n<script src=\"/path/to/nej/define.js?p=wk|gk|td\"></script>\n```\n\n```html\n<script src=\"/path/to/nej/define.js?p=cef\"></script>\n```\n\n### 平台变更\n\n通过以上实现举例我们可以看到当平台发生变更时我们可以快速进行扩展或缩减\n\n#### 平台扩展\n\n当有新平台需要作为系统目标平台时，我们只需要做以下工作：\n\n* 增加平台配置识别符，如nxw\n* 识别该平台与标准存在的差异，增加平台特有业务逻辑至patch\n* 系统对平台配置部分增加新添的识别符，如\n\n    原平台适配\n    ```html\n    <script src=\"/path/to/nej/define.js?p=wk|gk|td\"></script>\n    ```\n\n    新增平台适配\n    ```html\n    <script src=\"/path/to/nej/define.js?p=wk|gk|td|nxw\"></script>\n    ```\n\n即可完成对平台的扩展，而不会影响到原有的业务逻辑\n\n#### 平台缩减\n\n当系统适配的目标平台由于某种原因退出历史舞台时，系统也需要将该平台的冗余代码从系统中剔除，我们只需要做以下工作：\n\n* 系统对平台配置部分删除要剔除的平台标识，如\n\n    原平台适配\n    ```html\n    <script src=\"/path/to/nej/define.js?p=wk|gk|td\"></script>\n    ```\n\n    缩减后平台适配\n    ```html\n    <script src=\"/path/to/nej/define.js?p=wk\"></script>\n    ```\n\n即可完成对平台的缩减，而无需修改任何业务逻辑\n\n## 模块的可伸缩性\n\nWEB交互式系统对模块的可伸缩性同样表现为：\n\n* 可扩展性：对于系统新增的功能需求能够快速响应支持\n* 可缩减性：对于系统退化的模块能够以最小的修改方式剔除\n\n这里我们提供一套模块调度的系统架构模式用于支持单页富应用系统的设计架构、模块拆分、模块重组、调度管理等功能\n\n### 模块\n\n这里我们定义的模块是指从系统中拆分出来的可与用户进行交互完成一部分完整功能的独立单元\n\n#### 模块组成\n\n因为这里描述的模块可独立与用户完成交互功能，因此模块会包含以下元素\n\n* 样式：定义模块的效果\n* 结构：定义模块的结构\n* 逻辑：实现模块的功能\n\n以上元素对于一个WEB系统开发者来说并不陌生，而我们只需要寻求一种形式将这些内容封装起来即可\n\n#### 模块封装\n\n从模块的组成我们可以看到系统中分离出来的模块可能会长成这个样子，比如module.html就是我们分离出来的一个模块\n\n当然这里也可以用脚本文件封装，样式和结构采用注入形式，我们这里以html文件封装举例\n\n```html\n<!-- 模块样式 -->\n<style>\n    .m-mdl-1 .a{color:#aaa;}\n    .m-mdl-1 .b{color:#bbb;}\n\n    /* 此处省略若干内容 */\n</style>\n\n<!-- 模块结构 -->\n<div class=\"m-mdl-1\">\n  <p class=\"a\">aaaaaaaaaaaaaaaaaaa</p>\n  <p class=\"b\">bbbbbbbbbbbbbbbbbbb</p>\n\n  <!-- 此处省略若干内容 -->\n</div>\n\n<!-- 模块逻辑 -->\n<script>\n    (function(){\n        var a = 'aaa';\n        var b = 'bbb';\n\n        // 此处省略若干内容\n    })();\n</script>\n```\n\n而这个模块在用户需要时加载到客户端，并展现出来跟用户进行交互，完成功能，但是我们会发现如果系统预加载了此模块或者模块在parse时这些内容会被直接执行，而这个结果并不是我们需要的，因此我们需要将模块的各元素文本化处理，文本化处理有多种方式，如作为文本script、textarea等标签内容，因此module.html里的模块我们可以封装成如下样子，以textarea举例：\n\n```html\n<!-- 模块样式 -->\n<textarea name=\"css\">\n    .m-mdl-1 .a{color:#aaa;}\n    .m-mdl-1 .b{color:#bbb;}\n\n    /* 此处省略若干内容 */\n</textarea>\n\n<!-- 模块结构 -->\n<textarea name=\"html\">\n    <div class=\"m-mdl-1\">\n      <p class=\"a\">aaaaaaaaaaaaaaaaaaa</p>\n      <p class=\"b\">bbbbbbbbbbbbbbbbbbb</p>\n\n      <!-- 此处省略若干内容 -->\n    </div>\n</textarea>\n\n<!-- 模块逻辑 -->\n<textarea name=\"js\">\n    (function(){\n        var a = 'aaa';\n        var b = 'bbb';\n\n        // 此处省略若干内容\n    })();\n</textarea>\n```\n\n### 管理依赖\n\n从系统中拆分出来的模块之间是存在有一定关系的，如一个模块的呈现必须依赖另外一个模块的呈现，下面我们会以一个简单的例子来讲解模块之间的依赖管理，如下图是我们的一个单页应用系统\n\n![单页富应用范例](http://nej.netease.com/images/sample.gif)\n\n从上图不难看出整个系统包含以下几部分内容：\n\n* 日志管理\n\n  * 日志：日志列表，可切换收件箱/草稿箱/回收站/标签\n  * 标签：标签列表，可转至日志按标签查看列表\n\n* 博客设置\n\n  * 账号管理\n\n    * 基本资料：用户基本资料设置表单\n    * 个人经历：个人经历填写表单\n\n  * 权限设置：权限设置表单\n\n而这些模块之间的层级关系则如下所示\n\n![模块层级结构图](http://img0.ph.126.net/7ixXaTU-uFtbe0pKCWCgPA==/6597270977286264717.png)\n\n针对交互式系统的这种层级架构典型的模式可以参阅\n\n* [PAC（Presentation－Abstraction－Control）模式](http://en.wikipedia.org/wiki/Presentation%E2%80%93abstraction%E2%80%93control)\n* [HMVC（Hierarchical model–view–controller）模式](http://en.wikipedia.org/wiki/Hierarchical_model%E2%80%93view%E2%80%93controller)\n\n然而在WEB交互式系统的实践过程中我们发现这种模式会存在一些缺陷：\n\n* 由于每个父模块自己维护了所有的子模块，因此父子模块之间耦合性过强，父模块必须耦合所有子模块\n* 由于模块之间不能直接越级调用，因此子模块需要其他模块协助时必须层层向上传递事件，如果层级过深则会影响到系统效率\n* 模块的增删等变化导致的变更涉及的影响较大，删除中间节点上的模块可能导致相邻的若干模块的变更\n* 多人协作开发系统时存在依赖关系的模块会导致开发人员之间的紧密耦合\n\n在这里我们给出了一种基于模块标识的依赖管理配置方案，可以彻底的将模块进行解耦，每个模块可以独立完整的完成自己的交互功能，而系统的整合则可以通过配置的方式灵活的重组各模块，模块的增删操作只需修改配置即可完成，而无需影响到具体业务逻辑\n\n下文我们会通过以上例子来讲解此方案的原理和实际操作方式\n\n#### 模块标识\n\n因为本方案会基于模块标识做配置，因此在介绍方案之前我们先介绍一下模块标识，这里我们给模块标识取名为**UMI**（Uniform Module Identifier）统一模块标识，下文简称UMI，遵循以下规则约定\n\n* 格式同URI的Path部分，如 /m/m0/\n* 必须以“/”符开始\n* 私有模块必须以“/?”开始\n* 承载模块的依赖关系，如 /m/m0/ 和 /m/m1/ 表明这两个标识对应模块的父模块标识均为 /m\n\n每个UMI均可唯一标识一个模块及模块在系统中的依赖关系，在模块章节我们介绍了一个模块可以用一个html进行封装，因此我们可以得到以下结果\n\n![UMI与模块地址映射关系图](http://img0.ph.126.net/DCSPjxzVgjlgc8B983YSSg==/2673167853921558567.png)\n\n每个UMI均可映射到一个模块实现文件，这样我们就可以将模块从具体实现中解耦出来，对模块的增删修改操作只需调整UMI和模块文件的映射关系即可，而无需涉及具体业务逻辑的修改\n\n#### 模块依赖\n\n在解决了模块与实现分离的问题后，我们接下来需要将层级式的模块扁平化来解耦模块之间的依赖关系\n\n回到前面的例子，模块之间的层级关系如下图所示\n\n![模块层级关系图](http://img1.ph.126.net/NFbfUjokCb1KsI8tCj04xw==/6608203421400487879.jpg)\n\n如果我们将图中的依赖关系进行抽象分离后可以发现所有的模块即可呈现扁平的状态\n\n![模块关系分离图](http://img1.ph.126.net/XByNuSHTyJ_OzmAFIcqGKQ==/6608480498329578217.png)\n\n而对于模块之前的依赖关系的管理在所有系统中都是一致的，但是每个模块的具体功能实现是由系统来决定的，不同的系统是截然不同的，因此本方案提供的解决方案主要是用来维护模块之间的依赖关系的\n\n从上图我们可以比较清楚的看到模块之间的依赖关系呈现树状结构，因此我们会以树的结构来组织维护模块之间的依赖关系，我们称之为依赖关系树，而当我们将这棵树上的任意节点与根节点之间的路径用“/”分隔序列化后发现刚好与我们提供的UMI是匹配的，因此组成系统的模块的UMI可以跟依赖关系树的节点一一对应起来，如下图所示\n\n![依赖关系树节点序列化成UMI](http://img2.ph.126.net/cu36voh3bRXFx530aW6nkg==/6608921402492317376.png)\n\n在模块标识章节我们介绍了UMI与模块封装文件可以相互映射，因此依赖关系树上的节点可以直接与模块的实现文件做一一对应，如下图所示\n\n![依赖关系树映射模块实现文件](http://img1.ph.126.net/6Pfkz1_4dd32jnL60QQ1Kw==/6608598146073751639.png)\n\n至此，我们将垂直层级依赖的模块通过依赖关系树分解成了无任何关系的扁平模块结构\n\n#### 模块组合\n\n模块只需要有个呈现容器即可渲染出来，因此模块如果需要能够做任意组合，只需将模块分成两种类型：提供容器的模块和使用容器的模块即可，当然一个模块可同时兼具提供容器和使用容器的功能，提供容器的模块和使用容器的模块可任意组合\n\n![模块组合](http://img2.ph.126.net/D446SK2cBk_aGZFLVRwIew==/3669307796500606643.png)\n\n对于模块组合的配置代码范例\n\n```javascript\n'/m/blog/list/':{\n    module:'module/layout/blog.list/index.html',\n    composite:{\n        box:'/?/blog/box/',\n        tag:'/?/blog/tag/',\n        list:'/?/blog/list/',\n        clazz:'/?/blog/class/'\n    }\n}\n```\n\n### 调度策略\n\n在将模块扁平化后，各模块就可以安排给不同的开发人员进行功能实现和测试了，各模块完成后根据依赖关系树进行系统整合，系统整合后各模块会遵循一定的调度策略进行调度\n\n#### 模块状态\n\n根据模块调度的阶段划分，模块的状态可以分为以下四种：\n\n* 模块构建：构建模块结构\n* 模块显示：将模块渲染到指定的容器中\n* 模块刷新：根据外界输入的参数信息获取数据并展示（这里主要做数据处理）\n* 模块隐藏：模块放至内存中，回收由显示和刷新阶段产生的额外数据及结构\n\n调度策略主要控制模块在这几个阶段之间的转换规则\n\n#### 模块显示\n\n当用户请求显示一个模块时各模块会遵循以下步骤进行调度，假设请求显示 /m/blog/list/ 模块\n\n![显示调度策略](http://img1.ph.126.net/ip4S9-mTCAH943VGwXZ1OQ==/6619563575537201227.png)\n\n1. 检查目标节点到根节点路径上注册的模块，如果注册的是模块的实现文件地址，则请求载入模块实现文件\n2. 如果节点所在的模块的所有祖先节点已显示，则当前模块可被显示出来，否则等待祖先模块的显示调度\n3. 模块载入后根据第二步骤原则尝试调度目标模块的显示\n\n#### 模块切换\n\n当用户从一个模块切换到另外一个模块时各模块遵循以下步骤调度，假设从 /m/blog/list/ 切换到 /m/setting/account/edu/ 模块\n\n![模块切换](http://img0.ph.126.net/ca9IdYk2ezLL-zN8vRqI4Q==/6619574570653479153.png)\n\n1. 查找源模块与目标模块的公共父节点\n\n   ![查找公共模块](http://img2.ph.126.net/G36CYcFsck1w8Uf0k7oOIw==/6608672912864439374.png)\n\n2. 从源节点到公共节点之间的模块调度隐藏操作\n\n   ![隐藏模块](http://img0.ph.126.net/kCydlPd-q7yUIQ2rc65Eyg==/6608818048399307052.png)\n\n3. 从根节点到公共节点之间的模块调度刷新操作\n\n   ![刷新模块](http://img2.ph.126.net/sN7NPW5etJ0FVjv-TyBL9w==/6608677310910950450.png)\n\n4. 从公共节点到目标节点之间的模块调度显示操作\n\n   ![显示模块](http://img1.ph.126.net/DwnLyinZy9ZG8IX_uwOmsg==/6599306173308730570.png)\n\n### 消息通道\n\n大部分时候我们不建议使用模块之前的消息通信，实践中也存在一些特殊情况会需要模块之前的消息通信，这里提供两种方式的消息通讯\n\n* 点对点的消息：一个模块发送消息时明确指定目标模块的UMI\n* 观察订阅消息：一个模块可以对外申明发布了什么样的消息，有需要的模块可以订阅该模块UMI上的消息\n\n### 实例分析\n\n[NEJ框架](https://github.com/NetEaseWD/NEJ)根据以上描述对此套架构模式做了实现，我们用上面的具体实例讲解如何使用NEJ中的模块调度系统来拆分一个复杂系统、开发测试模块、整合系统等\n\n#### 系统分解\n\n##### 绘制层级关系图\n\n当我们拿到一个复杂系统时根据交互稿可以绘制出组成系统的模块的层级关系图，并确定系统对外可访问的模块\n\n![模块层级关系图](http://img1.ph.126.net/UmNMLNzb-Vjdtv8skT8kqg==/6608742182096989774.png)\n\n##### 抽象依赖关系树\n\n从模块的层级关系图中我们可以非常方便的抽象出模块的依赖关系树\n\n![抽象依赖关系树](http://img1.ph.126.net/BK5_LhDhh01addpDJuY4Yw==/6619331578583739475.png)\n\n将抽象出来的依赖关系树根据UMI规则进行格式化，格式化的主要操作包括\n\n* 增加一个名称为“/”的根结点（也可将“m”结点改为“/”）\n* 每个结点增加“/”的子节点作为默认节点\n\n![格式化依赖关系树](http://img2.ph.126.net/5b3ByaubY0XFOlnU1PZHAw==/6619382156118617138.png)\n\n至此输出的依赖关系树，具有以下特性：\n\n* 任何一个结点（除根结点外）到根结点路径上的结点名称用“/”分隔组合起来即为结点的UMI值，如list结点的UMI值为/m/blog/list\n* 任何结点上的模块都依赖于他祖先结点（注册有模块）上的模块存在，如blog结点和list结点均注册有模块，则list结点上的模块显示必须以blog结点上的模块的显示为先决条件\n\n##### 确定对外模块注册节点\n\n五个对外可访问的模块：日志、标签、基本资料、个人经历、权限设置，在依赖关系树中找到合适的结点（叶子结点，层级关系树在依赖关系树中对应的结点或“/”结点）来注册对外可访问的模块\n\n![对外模块注册节点](http://img0.ph.126.net/vC28JzPSddgzZdpEAeBZ2w==/6619485510211628655.png)\n\n##### 确定布局模块注册节点\n\n从可访问模块注册的结点往根结点遍历，凡碰到两模块交叉的结点即为布局模块注册结点，系统所需的组件相关的模块可注册到根结点，这样任何模块使用的时候都可以保证这些组件已经被载入\n\n![布局模块注册节点](http://img1.ph.126.net/Jjp0GCDfh2eXvaxJvhiCeQ==/6619215030351195733.png)\n\n##### 映射模块功能\n\n原则：结点的公共父结点实现结点上注册的模块的公共功能\n\n举例：blog结点和setting结点的公共父结点为m结点，则我们可以通过切换blog模块和setting模块识别不变的功能即为m模块实现的功能，同理其他模块\n\n![功能映射](http://img2.ph.126.net/64xhHIfGy4qdQKSV5Bym-g==/2679360303409193237.png)\n\n##### 分解复杂模块\n\n进一步分解复杂模块，一般需要分解的模块包括：\n\n* 可共用模块，比如日志列表，可以在日志管理页面呈现，也可以在弹层中显示\n* 逻辑上无必然联系的模块，如日志模块中日志列表与右侧的按标签查看的标签列表之间没有必然的联系，任何一个模块的移除或添加都不会影响到另外一个模块的业务逻辑\n\n![分解复杂模块](http://img1.ph.126.net/wRM1uAxQDRFhfAzlNw8b5Q==/6599274287471525959.png)\n\n至此我们可以得到两棵系统分解后的依赖关系树\n\n对外模块依赖关系树\n\n![对外模块依赖关系树](http://img2.ph.126.net/6yAKfH-sST3-RGc0xIxU2g==/6608788361585356880.png)\n\n私有模块依赖关系树\n\n![私有模块依赖关系树](http://img1.ph.126.net/KgimU46Zn4ZnUtxiBrXdKw==/6608191326772584502.png)\n\n##### 绘制模块功能规范表\n\n本例中为了说明分解过程将所有可分解的模块都做了分解，实际项目看具体情况，比如这里的/m模块组合的/?/tab/模块的功能可以直接在/m模块中实现，而不需要新建一个/?/tab/模块来实现这个功能\n\n规范表范例如下所示\n\n![功能规范表](http://img1.ph.126.net/e_0ZFwbefuXT5bZ6bq17Rg==/1496320976294650210.png)\n\n#### 构建目录\n\n##### 项目目录\n\n项目目录的构建如下图所示\n\n![项目目录](http://img0.ph.126.net/7mfjeInfGILw-tWQznxxLA==/6608777366469080397.png)\n\n各目录说明\n\n```\nwebroot                    项目前端开发相关目录\n   |- res                  静态资源文件目录，打包时可配置使用到该目录下的静态资源带版本信息\n   |- src                  前端源码目录，最终发布时该目录不会部署到线上\n       |- html\n            |- module      单页面模块目录，系统所有模块的实现均在此目录下\n            |- app.html    单页面入口文件\n```\n\n##### 模块单元目录\n\n根据模块封装规则一个模块单元由以下几部分组成：\n\n* 模块测试：模块实现的功能可以通过模块测试页面独立进行测试\n* 模块结构：模块所涉及的结构分解出来的若干模板集合\n* 模块逻辑：根据模块规范实现的模块业务逻辑，从模块基类继承\n* 模块样式：模块特有的样式，一般情况下这部分样式可以直接在css目录下实现\n\n结构范例如下所示\n\n![模块单元目录](http://img0.ph.126.net/o6dTV8RpqAtS63zxdz8sEg==/6608917004445806742.png)\n\n至此我们可以得到所有模块的目录结构如下所示\n\n![模块目录结构](http://img0.ph.126.net/2cMlaKsMBzOfAPPdH9IzkA==/6608797157678379135.png)\n\n#### 模块实现\n\n##### 结构\n\n这里我们假设系统的静态页面已经做完，这里的模块实现只是在原有结构的基础上进行结构分解和业务逻辑的实现，结构部分内容主要将模块相关的静态结构拆分成若干NEJ的模板，注意：\n\n* 模板中的外联资源如css，js文件地址如果使用的是相对路径则均相对于模块的html文件路径\n* 模板集合中的外联资源必须使用@TEMPLATE标记标识，这个在后面打包发布章节会详细介绍\n\nNEJ模板说明\n\n![NEJ模板](http://img2.ph.126.net/W_RhwYyx4kbPPGMpcVoUwQ==/6608414527633039667.png)\n\n模块结构举例\n\n```html\n<meta charset=\"utf-8\"/>\n\n<textarea name=\"txt\" id=\"m-ifrm-module\">\n  <div class=\"n-login\">\n    <div class=\"iner j-flag\">\n      <span class=\"cls j-flag\">×</span>\n      <span class=\"min j-flag\">－</span>\n    </div>\n    <div class=\"cnt j-cnt\"></div>\n  </div>\n</textarea>\n\n\n<textarea name=\"js\" data-src=\"./index.css\"></textarea>\n<textarea name=\"js\" data-src=\"./index.js\"></textarea>\n\n```\n\n##### 逻辑\n\n依赖util/dispatcher/module模块，从_$$ModuleAbstract扩展一个项目的模块基类，完成项目中模块特有属性、行为的抽象\n\n```javascript\n/*\n * ------------------------------------------\n * 项目模块基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/klass',\n    'util/dispatcher/module'\n],function(_k,_t,_p){\n    // variable declaration\n    var _pro;\n    /**\n     * 项目模块基类对象\n     * @class   {_$$Module}\n     * @extends {_$$ModuleAbstract}\n     * @param   {Object}  可选配置参数，已处理参数列表如下所示\n     */\n    _p._$$Module = _k._$klass();\n    _pro = _p._$$Module._$extend(_t._$$ModuleAbstract);\n    /**\n     * 操作\n     * @param  {Object}\n     * @return {Void}\n     */\n    _pro.__doSomething = function(_args){\n        // TODO\n    };\n\n    // TODO\n\n    return _p;\n});\n```\n\n根据模块状态的划分，我们在实现一个模块时需要实现以下几个接口\n\n![模块各阶段接口](http://img0.ph.126.net/8XyKVwG3dzG0dK59qteZFw==/6619467918025585071.png)\n\n各阶段对应的接口：\n\n* 构建 - \\_\\_doBuild：构建模块结构，缓存模块需要使用的节点，初始化组合控件的配置参数\n* 显示 - \\_\\_onShow：将模块放置到指定的容器中，分配组合控件，添加相关事件，执行\\_\\_onRefresh的业务逻辑\n* 刷新 - \\_\\_onRefresh：根据外界输入的参数信息获取数据并展示（这里主要做数据处理）\n* 隐藏 - \\_\\_onHide：模块放至内存中，回收在\\_\\_onShow中分配的组合控件和添加的事件，回收\\_\\_onRefresh中产生的视图（这里尽量保证执行完成后恢复到\\_\\_doBuild后的状态）\n\n具体模块实现举例\n\n```javascript\n/*\n * ------------------------------------------\n * 项目模块实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/klass',\n    'util/dispatcher/module',\n    '/path/to/project/module.js'\n],function(_k,_e,_t,_p){\n    // variable declaration\n    var _pro;\n    /**\n     * 项目模块对象\n     * @class   {_$$ModuleDemo}\n     * @extends {_$$Module}\n     * @param   {Object} 可选配置参数\n     */\n    _p._$$ModuleDemo = _k._$klass();\n    _pro = _p._$$ModuleDemo._$extend(_t._$$Module);\n    /**\n     * 构建模块，主要处理以下业务逻辑\n     * - 构建模块结构\n     * - 缓存后续需要使用的节点\n     * - 初始化需要使用的组件的配置信息\n     * @return {Void}\n     */\n    _pro.__doBuild = function(){\n        this.__super();\n        // TODO\n    };\n    /**\n     * 显示模块，主要处理以下业务逻辑\n     * - 添加事件\n     * - 分配组件\n     * - 处理输入信息\n     * @param  {Object} 输入参数\n     * @return {Void}\n     */\n    _pro.__onShow = function(_options){\n        this.__super(_options);\n        // TODO\n    };\n    /**\n     * 刷新模块，主要处理以下业务逻辑\n     * - 分配组件，分配之前需验证\n     * - 处理输入信息\n     * - 同步状态\n     * - 载入数据\n     * @return {Void}\n     */\n    _pro.__onRefresh = function(_options){\n        this.__super(_options);\n        // TODO\n    };\n    /**\n     * 隐藏模块，主要处理以下业务逻辑\n     * - 回收事件\n     * - 回收组件\n     * - 尽量保证恢复到构建时的状态\n     * @return {Void}\n     */\n    _pro.__onHide = function(){\n        this.__super();\n        // TODO\n    };\n    // notify dispatcher\n    _e._$regist(\n        'umi_or_alias',\n        _p._$$ModuleDemo\n    );\n\n    return _p;\n});\n```\n\n##### 消息\n\n###### 点对点消息\n\n模块可以通过\\_\\_doSendMessage接口向指定UMI的模块发送消息，也可以通过实现\\_\\_onMessage接口来接收其他模块发给他的消息\n\n发送消息\n\n```javascript\n_pro.__doSomething = function(){\n\n    // TODO\n\n    this.__doSendMessage(\n        '/m/setting/account/',{\n            a:'aaaaaa',\n            b:'bbbbbbbbb'\n        }\n    );\n};\n```\n\n接收消息\n\n```javascript\n_pro.__onMessage = function(_event){\n    // _event.from 消息来源\n    // _event.data 消息数据，这里可能是 {a:'aaaaaa',b:'bbbbbbbbb'}\n\n    // TODO\n};\n```\n\n###### 发布订阅消息\n\n发布消息\n\n```javascript\n_pro.__doSomething = function(){\n\n    // TODO\n\n    this.__doPublishMessage(\n        'onok',{\n            a:'aaaaaa',\n            b:'bbbbbbbb'\n        }\n    );\n};\n```\n\n订阅消息\n\n```javascript\n_pro.__doBuild = function(){\n\n    // TODO\n\n    this.__doSubscribeMessage(\n        '/m/message/account/','onok',\n        this.__onMessageReceive._$bind(this)\n    );\n};\n```\n\n##### 自测\n\n创建html页面，使用模板引入模块实现文件\n\n```html\n<!-- template box -->\n<div id=\"template-box\" style=\"display:none;\">\n  <textarea name=\"html\" data-src=\"../index.html\"></textarea>\n</div>\n```\n\n模块放至document.mbody指定的容器中\n\n```javascript\nNEJ.define([\n    'util/dispatcher/test'\n],function(_e){\n    document.mbody = 'module-id-0';\n    // test module\n    _e._$testByTemplate('template-box');\n});\n```\n\n#### 系统整合\n\n##### 映射依赖关系树\n\n系统整合时，我们只需要将依赖关系树中需要注册模块的节点同模块实现文件进行映射即可\n\n对外模块整合\n\n![对外模块整合](http://img2.ph.126.net/CQe6y5Bdgkl4bA5VsSIwzA==/6608893914701623469.png)\n\n私有模块整合\n\n![私有模块整合](http://img0.ph.126.net/upKrOu1fEmK_Q6x2jc-ibA==/6619430534630239416.png)\n\n##### 提取系统配置信息\n\n规则配置举例\n\n```javascript\n  rules:{\n      rewrite:{\n          '404':'/m/blog/list/',\n          '/m/blog/list/':'/m/blog/',\n          '/m/setting/account/':'/m/setting/'\n      },\n      title:{\n          '/m/blog/tag/':'日志标签',\n          '/m/blog/list/':'日志列表',\n          '/m/setting/permission/':'权限管理',\n          '/m/setting/account/':'基本资料',\n          '/m/setting/account/edu/':'教育经历'\n      },\n      alias:{\n          'system-tab':'/?/tab/',\n          'blog-tab':'/?/blog/tab/',\n          'blog-list-box':'/?/blog/box/',\n          'blog-list-tag':'/?/blog/tag/',\n          'blog-list-class':'/?/blog/class/',\n          'blog-list':'/?/blog/list/',\n          'setting-tab':'/?/setting/tab/',\n          'setting-account-tab':'/?/setting/account/tab/',\n\n          'layout-system':'/m',\n          'layout-blog':'/m/blog',\n          'layout-blog-list':'/m/blog/list/',\n          'layout-setting':'/m/setting',\n          'layout-setting-account':'/m/setting/account',\n\n          'blog-tag':'/m/blog/tag/',\n          'setting-edu':'/m/setting/account/edu/',\n          'setting-profile':'/m/setting/account/',\n          'setting-permission':'/m/setting/permission/'\n      }\n  }\n```\n\n模块配置举例\n\n```javascript\n  modules:{\n      '/?/tab/':'module/tab/index.html',\n      '/?/blog/tab/':'module/blog/tab/index.html',\n      '/?/blog/box/':'module/blog/list.box/index.html',\n      '/?/blog/tag/':'module/blog/list.tag/index.html',\n      '/?/blog/class/':'module/blog/list.class/index.html',\n      '/?/blog/list/':'module/blog/list/index.html',\n      '/?/setting/tab/':'module/setting/tab/index.html',\n      '/?/setting/account/tab/':'module/setting/account.tab/index.html',\n\n      '/m':{\n          module:'module/layout/system/index.html',\n          composite:{\n              tab:'/?/tab/'\n          }\n      },\n      '/m/blog':{\n          module:'module/layout/blog/index.html',\n          composite:{\n              tab:'/?/blog/tab/'\n          }\n      },\n      '/m/blog/list/':{\n          module:'module/layout/blog.list/index.html',\n          composite:{\n              box:'/?/blog/box/',\n              tag:'/?/blog/tag/',\n              list:'/?/blog/list/',\n              clazz:'/?/blog/class/'\n          }\n      },\n      '/m/blog/tag/':'module/blog/tag/index.html',\n\n      '/m/setting':{\n          module:'module/layout/setting/index.html',\n          composite:{\n              tab:'/?/setting/tab/'\n          }\n      },\n      '/m/setting/account':{\n          module:'module/layout/setting.account/index.html',\n          composite:{\n              tab:'/?/setting/account/tab/'\n          }\n      },\n      '/m/setting/account/':'module/setting/profile/index.html',\n      '/m/setting/account/edu/':'module/setting/edu/index.html',\n      '/m/setting/permission/':'module/setting/permission/index.html'\n  }\n```\n\n##### 模块组合\n\n模块通过\\_\\_export属性开放组合模块的容器，\\_\\_export中的parent为子模块的容器节点，顶层模块（如 “/m”）可以通过重写\\_\\_doParseParent来明确指定应用所在容器\n\n```javascript\n_pro.__doBuild = function(){\n    this.__body = _e._$html2node(\n        _e._$getTextTemplate('module-id-l2')\n    );\n    // 0 - box select\n    // 1 - class list box\n    // 2 - tag list box\n    // 3 - sub module box\n    var _list = _e._$getByClassName(this.__body,'j-flag');\n    this.__export = {\n        box:_list[0],\n        clazz:_list[1],\n        tag:_list[2],\n        list:_list[3],\n        parent:_list[3]\n    };\n};\n```\n\n通过composite配置模块组合\n\n```javascript\n'/m/blog/list/':{\n    module:'module/layout/blog.list/index.html',\n    composite:{\n        box:'/?/blog/box/',\n        tag:'/?/blog/tag/',\n        list:'/?/blog/list/',\n        clazz:'/?/blog/class/'\n    }\n}\n```\n\n模块组合时可以指定组合模块的处理状态\n* onshow  - 这里配置的组合模块仅在模块显示时组合，后续的模块refresh操作不会导致组合模块的refresh，适合于模块在显示后不会随外界输入变化而变化的模块\n* onrefresh  -  这里配置的模块在模块显示时组合，后续如果模块refresh时也会跟随做refresh操作，适用于组合的模块需要与外部输入同步的模块\n* 不指定onshow或者onrefresh的模块等价于onrefresh配置的模块\n\n```javascript\ncomposite:{\n    onshow:{\n        // 模块onshow时组合\n        // 组合的模块在模块onrefresh时不会刷新\n    },\n    onrefresh{\n        // 模块onshow时组合\n        // 组合的模块在模块onrefresh时也同时会刷新\n    }\n    // 这里配置的组合模块等价于onrefresh中配置的模块\n}\n```\n\n##### 启动应用\n\n根据配置启动应用\n\n```javascript\nNEJ.define([\n    'util/dispatcher/dispatcher'\n],function(_e){\n    _e._$startup({\n        // 规则配置\n        rules:{\n            rewrite:{\n                // 重写规则配置\n            },\n            title:{\n                // 标题配置\n            },\n            alias:{\n                // 别名配置\n                // 建议模块实现文件中的注册采用这里配置的别名\n            }\n        },\n        // 模块配置\n        modules:{\n            // 模块UMI对应实现文件的映射表\n            // 同时完成模块的组合\n        }\n    });\n});\n```\n\n#### 打包发布\n\n打包发布内容详见[NEJ工具集](https://github.com/genify/toolkit)相关文档\n\n### 系统变更\n\n当系统需求变化而进行模块变更我们只需要开发新的模块或删除模块配置即可\n\n#### 新增模块\n\n如果增加一个全新的模块则只需按照上面的逻辑实现步骤开发一个模块即可\n\n如果新增的模块功能在系统中已经实现，则只需修改配置即可，如上例中我们需要在将日志管理下的标签模块在博客设置中也加一份，访问路径为/m/setting/tag/\n\n![新增模块](http://img0.ph.126.net/s4pv6FZmPal8Jx0m0eNltA==/6619471216560468933.png)\n\n修改规则配置\n\n```javascript\nrules:{\n    // ...\n    alias:{\n        // ...\n        'blog-tag':['/m/blog/tag/','/m/setting/tag/']\n    }\n}\n```\n\n修改模块配置\n\n```javascript\nmodules:{\n    // ...\n    '/m/setting/tag/':'module/blog/tag/index.html'\n}\n```\n\n如果要在/?/setting/tab模块的结构模板中增加一个标签即可\n\n```html\n<textarea name=\"txt\" id=\"module-id-8\">\n  <div class=\"ma-t w-tab f-cb\">\n    <a class=\"itm fl\" href=\"#/setting/account/\" data-id=\"/setting/account/\">账号管理</a>\n    <a class=\"itm fl\" href=\"#/setting/permission/\" data-id=\"/setting/permission/\">权限设置</a>\n    <a class=\"itm fl\" href=\"#/setting/tag/\" data-id=\"/setting/tag/\">日志标签</a>\n  </div>\n</textarea>\n```\n\n#### 删除模块\n\n将退化的模块从系统中删除只需要将模块对应的UMI配置从模块配置中删除即可，而无需修改具体业务逻辑\n\n## 总结\n\n随着WEB技术的快速发展，单页面系统（[SPA](http://en.wikipedia.org/wiki/Single-page_application)）的应用变得越来越广泛；随着此类系统复杂度的增加，其对平台及模块的伸缩性方面需求变得越来越重要，而对于这两方面业界也有不少解决方案业，本文我们主要探讨了网易[NEJ框架](https://github.com/NetEaseWD/NEJ)在这些方面给出的解决方案；网易在单页面系统方面也做了多年的实践和技术积累，如 近几年的[网易云音乐PC版](http://music.163.com/#/download)、[易信WebIM](https://web.yixin.im/)、[网易邮箱助手](http://mailease.163.com/)等，早些年的 [网易相册](http://photo.163.com/)、[网易邮箱](http://mail.163.com)等，移动端的[网易云相册IPad版](http://photo.163.com/cloudphotos/)、[Lofter Android版](http://www.lofter.com/app)等产品均是此类单页面系统的应用实践，如实践过程中对这方面有兴趣的同学可进一步做交流\n"
  },
  {
    "path": "package.json",
    "content": "{\n    \"name\": \"nej-framework\",\n    \"description\": \"JavaScript Cross-Platform Framework\",\n    \"version\": \"0.5.2\",\n    \"license\": \"MIT\",\n    \"keywords\": [\n        \"nej\",\n        \"javascript\",\n        \"cross platform\",\n        \"framework\"\n    ],\n    \"author\": \"genify <caijf@corp.netease.com>\",\n    \"main\": \"./src/define.js\",\n    \"homepage\": \"https://github.com/genify/nej\",\n    \"scripts\": {\n        \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n    },\n    \"repository\": {\n        \"type\": \"git\",\n        \"url\": \"https://github.com/genify/nej.git\"\n    },\n    \"bugs\": {\n        \"url\": \"https://github.com/genify/nej/issues\"\n    }\n}"
  },
  {
    "path": "res/crossdomain.xml",
    "content": "<?xml version=\"1.0\"?>\n<cross-domain-policy> \n  <site-control permitted-cross-domain-policies=\"by-content-type\"/> \n  <allow-access-from secure=\"true\" domain=\"*\"/> \n</cross-domain-policy>"
  },
  {
    "path": "res/nej_proxy_frame.html",
    "content": "<html> <head> <title>NEJ AJAX PROXY</title> <meta charset=\"utf-8\"/> \n<script>window.whitelist=[/.*/i];</script> \n<script>!function(){var e=[];window.addMsgListener=function(n){e.push(n)};var n=function(n){for(var t=0,r=e.length;t<r;t++)try{e[t].call(null,n)}catch(o){}};if(!window.postMessage){var t=\"MSG|\",r=[];var o=function(){var e=function(e){var n={},t=e.split(\"|\");for(var r=0,o=t.length,a;r<o;r++){a=t[r].split(\"=\");n[decodeURIComponent(a.shift())]=decodeURIComponent(a.join(\"=\"))}return n};return function(){var r=unescape(window.name||\"\");if(r&&0==r.indexOf(t)){window.name=\"\";r=r.replace(t,\"\");var o=e(r),a=(o.origin||\"\").toLowerCase();if(!a||\"*\"==a||0==location.href.toLowerCase().indexOf(a))n({data:o.data,origin:document.referrer})}}}();var a=function(){var e;var n=function(e,n){for(var t=0,r=e.length;t<r;t++)if(e[t]==n)return!0;return!1};return function(){if(r.length){e=[];for(var t=r.length-1,o;t>=0;t--){o=r[t];if(!n(e,o.w)){e.push(o.w);r.splice(t,1);o.w.name=o.d}}e=null}}}();window.doPostMessage=function(){var e=function(e){var n=[];for(var t in e)n.push(encodeURIComponent(t)+\"=\"+encodeURIComponent(e[t]));return n.join(\"|\")};var n=function(n){var r={};n=n||{};r.origin=n.origin||\"*\";r.ref=location.href;r.data=\"\"+n.data;return t+e(r)};return function(e,t){r.unshift({w:e,d:escape(n(t))})}}();window.setInterval(a,100);window.setInterval(o,50)}else{window.doPostMessage=function(e,n){n=n||{};e.postMessage(\"\"+n.data,n.origin||\"*\")};if(window.addEventListener)window.addEventListener(\"message\",n,!1);else window.attachEvent(\"onmessage\",n)}}();!function(){var e=function(){var e=document.referrer||\"\";if(!e||!whitelist.length)return!1;for(var n=0,t=whitelist.length,r;n<t;n++){r=whitelist[n];if(r.test&&r.test(e)||e==r)return!0}return!1};if(e()){var n=function(){};var t=function(e,n){try{n=n.toLowerCase();if(null===e)return\"null\"==n;if(void 0===e)return\"undefined\"==n;else return Object.prototype.toString.call(e).toLowerCase()==\"[object \"+n+\"]\"}catch(t){return!1}};var r=function(e){var n=[];for(var t in e)if(e.hasOwnProperty(t))n.push(encodeURIComponent(t)+\"=\"+encodeURIComponent(e[t]));else;return n.join(\"&\")};var o=function(){var e=/\"/gi,o=[\"Msxml2.XMLHTTP.6.0\",\"Msxml2.XMLHTTP.3.0\"];var a=function(){if(window.XMLHttpRequest)return new XMLHttpRequest;try{for(var e=0,n=o.length;e<n;e++)return new ActiveXObject(o[e])}catch(t){return null}};var i=function(n){var t='NEJ-AJAX-DATA:{                          \"key\":\"'+n.key+'\",                          \"status\":\"'+n.status+'\",                          \"result\":\"'+encodeURIComponent(n.result)+'\"                      }';if(!window.postMessage)t='\"'+t.replace(e,'\\\\\"')+'\"';window.doPostMessage(parent,{data:t})};return function(e){if(e&&e.url){var o=a(),u=e.key;var s,f=parseInt(e.timeout)||0;if(f)s=window.setTimeout(function(){o.onreadystatechange=n;o.abort();i({key:u,status:-1})},f);o.onreadystatechange=function(){if(4==o.readyState){window.clearTimeout(s);i({key:u,status:o.status,result:o.responseText||\"\"})}};o.open(e.method||\"GET\",e.url,!0);var c=e.headers||{};for(var d in c)o.setRequestHeader(d,c[d]);var w=e.data;if(t(w,\"object\"))w=r(w);o.send(w)}}}();var a=function(){var e=function(e){try{return new Function(\"return \"+e)()}catch(n){return null}};return function(n){if(\"string\"!=typeof n)return n;try{if(window.JSON&&JSON.parse)return JSON.parse(n)}catch(t){return n}return e(n)}}();window.addMsgListener(function(e){o(a(e.data))})}}();</script>\n</head> <body></body> </html>"
  },
  {
    "path": "res/nej_proxy_upload.html",
    "content": "<html><body>\n<!-- 将上传结果序列化为JSON串后填入result中即可 -->\n<script>\n    window.result = '{\"url\":\"http://192.168.146.84:1122/xhr/3.jpg\"}';\n</script>\n<script>\n    var _result = 'NEJ-UPLOAD-RESULT:{\"key\":\"'+window.name+'\",\"result\":\"'+encodeURIComponent(result)+'\"}';\n    if (window.postMessage){\n        parent.postMessage(_result,'*');\n    }else{\n        _result = '\"'+_result.replace(/\"/g,'\\\\\"')+'\"';\n        parent.name = escape('MSG|data='+encodeURIComponent(_result));\n    }\n</script>\n</body></html>"
  },
  {
    "path": "res/src/nej_proxy_frame.html",
    "content": "<html>\n  <head>\n    <title>NEJ AJAX PROXY</title>\n    <meta charset=\"utf-8\"/>\n    <script>window.whitelist = [/.*/i];</script>\n    <script>\n      // for post message and onmessage event\n      (function(){\n          var _listeners = [];\n          window.addMsgListener = function(_hanlder){\n              _listeners.push(_hanlder);\n          };\n          var _onMessage = function(_event){\n              for(var i=0,l=_listeners.length;i<l;i++)\n                  try{_listeners[i].call(null,_event);}catch(e){}\n          };\n          if (!!window.postMessage){\n              window.doPostMessage = function(_window,_options){\n                  _options = _options||{};\n                  _window.postMessage(''+_options.data,_options.origin||'*');\n              };\n              if (!!window.addEventListener){\n                  window.addEventListener('message',_onMessage,!1);\n              }else{\n                  window.attachEvent('onmessage',_onMessage);\n              }\n              return;\n          }\n          var _key = 'MSG|',\n              _queue = [];\n          /*\n           * 检测window.name变化情况\n           * @return {Void}\n           */\n          var _doCheckWindowName = (function(){\n              var _doStringObject = function(_string){\n                  var _result = {},\n                      _arr = _string.split('|');\n                  for(var i=0,l=_arr.length,_brr;i<l;i++){\n                      _brr = _arr[i].split('=');\n                      _result[decodeURIComponent(_brr.shift())]\n                            = decodeURIComponent(_brr.join('='));\n                  }\n                  return _result;\n              };\n              return function(){\n                  // check name\n                  var _name = unescape(window.name||'');\n                  if (!_name||_name.indexOf(_key)!=0) return;\n                  // clear name\n                  window.name = '';\n                  _name = _name.replace(_key,'');\n                  // onmessage trigger\n                  var _options = _doStringObject(_name),\n                      _origin = (_options.origin||'').toLowerCase();\n                  // check origin\n                  if (!!_origin&&_origin!='*'&&\n                      location.href.toLowerCase().indexOf(_origin)!=0)\n                      return;\n                  _onMessage({\n                      data:_options.data,\n                      origin:document.referrer\n                  });\n              };\n          })();\n          /*\n           * 检查待设置消息\n           * @return {Void}\n           */\n          var _doCheckNameQueue = (function(){\n              var _check;\n              var _hasItem = function(_list,_item){\n                  for(var i=0,l=_list.length;i<l;i++)\n                      if (_list[i]==_item)\n                          return !0;\n                  return !1;\n              };\n              return function(){\n                  if (!_queue.length) return;\n                  _check = [];\n                  for(var i=_queue.length-1,_map;i>=0;i--){\n                      _map = _queue[i];\n                      if (!_hasItem(_check,_map.w)){\n                          _check.push(_map.w);\n                          _queue.splice(i,1);\n                          _map.w.name = _map.d;\n                      }\n                  }\n                  _check = null;\n              };\n          })();\n          /**\n           * 发送消息\n           * @param  {Window} 窗体对象\n           * @param  {Object} 配置信息\n           * @config {String} data   消息内容，只支持字符串\n           * @config {String} origin 目标Origin，只有指定的页面可以收到消息，默认所有页面可收到消息，如http://a.b.com\n           * @return {Void}\n           */\n          window.doPostMessage = (function(){\n              // object to query\n              var _doQueryObject = function(_object){\n                  var _arr = [];\n                  for(var x in _object)\n                      _arr.push(encodeURIComponent(x)+'='+\n                                encodeURIComponent(_object[x]));\n                  return _arr.join('|');\n              };\n              // serialize send data\n              var _doSerialize = function(_data){\n                  var _result = {};\n                  _data = _data||{};\n                  _result.origin = _data.origin||'*';\n                  _result.ref  = location.href;\n                  _result.data = ''+_data.data;\n                  return _key+_doQueryObject(_result);\n              };\n              return function(_window,_options){\n                  _queue.unshift({w:_window,d:escape(_doSerialize(_options))});\n              };\n          })();\n          // init checker\n          window.setInterval(_doCheckNameQueue,100);\n          window.setInterval(_doCheckWindowName,50);\n      })();\n      // for ajax request\n      (function(){\n          // access control\n          var _hasPermission = function(){\n              var _ref = document.referrer||'';\n              if (!_ref||!whitelist.length) \n                  return !1;\n              for(var i=0,l=whitelist.length,_item;i<l;i++){\n                  _item = whitelist[i];\n                  if (!!_item.test&&\n                      _item.test(_ref)||_ref==_item)\n                      return !0;\n              }\n              return !1;\n          };\n          if (!_hasPermission()) return;\n          // ajax request implementation\n          var f = function(){};\n          var _isTypeOf = function(_data,_type){\n              try{\n                  _type = _type.toLowerCase();\n                  if (_data===null) return _type=='null';\n                  if (_data===undefined) return _type=='undefined';\n                  return Object.prototype.toString.call(_data).toLowerCase()=='[object '+_type+']';\n              }catch(e){\n                  return !1;\n              }\n          };\n          var _obj2str = function (obj) {\n              var ret = [];\n              for(var x in obj){\n                  if (!obj.hasOwnProperty(x)) continue;\n                  ret.push(encodeURIComponent(x)+'='+encodeURIComponent(obj[x]));\n              }\n              return ret.join('&');\n          };\n          /*\n           * 发送请求\n           * @param  {Object} 请求信息\n           * @config {String} key     请求标识，回调时传回\n           * @config {String} url     请求地址\n           * @config {String} method  请求方式，默认GET\n           * @config {Number} timeout 超时时间，默认不做超时检测\n           * @config {Object} headers 头信息\n           * @config {String} data    发送数据，字符串格式\n           * @return {Void}\n           */\n          var _doSendRequest = (function(){\n              var _reg0  = /\"/gi,\n                  _msxml = ['Msxml2.XMLHTTP.6.0'\n                           ,'Msxml2.XMLHTTP.3.0'];\n              var _getXHR = function(){\n                  if (window.XMLHttpRequest)\n                      return new XMLHttpRequest();\n                  try{\n                      for(var i=0,l=_msxml.length;i<l;i++)\n                          return new ActiveXObject(_msxml[i]);\n                  }catch(ex){\n                      return null;\n                  }\n              };\n              var _doCallback = function(_options){\n                  var _data = 'NEJ-AJAX-DATA:{\\\n                          \"key\":\"'+_options.key+'\",\\\n                          \"status\":\"'+_options.status+'\",\\\n                          \"result\":\"'+encodeURIComponent(_options.result)+'\"\\\n                      }';\n                  if (!window.postMessage)\n                      _data = '\"'+_data.replace(_reg0,'\\\\\"')+'\"';\n                  window.doPostMessage(parent,{data:_data});\n              };\n              return function(_options){\n                  if (!_options||!_options.url) return;\n                  var _xhr = _getXHR(),\n                      _key = _options.key;\n                  // set timeout\n                  var _timer,\n                      _timeout = parseInt(_options.timeout)||0;\n                  if (!!_timeout){\n                      _timer = window.setTimeout(function(){\n                          _xhr.onreadystatechange = f;\n                          _xhr.abort();\n                          _doCallback({key:_key,status:-1});\n                      },_timeout);\n                  }\n                  // set callback\n                  _xhr.onreadystatechange = function(){\n                      if (_xhr.readyState!=4) return;\n                      window.clearTimeout(_timer);\n                      _doCallback({\n                          key:_key,\n                          status:_xhr.status,\n                          result:_xhr.responseText||''\n                      });\n                  };\n                  _xhr.open(_options.method||'GET',_options.url,!0);\n                  // set headers\n                  var _headers = _options.headers||{};\n                  for(var x in _headers)\n                      _xhr.setRequestHeader(x,_headers[x]);\n                  // fix object to query string\n                  var dat = _options.data;\n                  if (_isTypeOf(dat,'object')){\n                      dat = _obj2str(dat);\n                  }\n                  _xhr.send(dat);\n              };\n          })();\n          /*\n           * 解析JSON\n           * @param  {String}   JSON串\n           * @return {Variable} JSON值\n           */\n          var _doParseJSON = (function(){\n              var _doEvalScript = function(_content){\n                  try{\n                      return (new Function('return '+_content))();\n                  }catch(e){\n                      return null;\n                  }\n              };\n              return function(_content){\n                  if (typeof(_content)!='string')\n                      return _content;\n                  try{\n                      if (!!window.JSON&&!!JSON.parse)\n                          return JSON.parse(_content);\n                  }catch(e){\n                      return _content;\n                  }\n                  return _doEvalScript(_content);\n              };\n          })();\n          // listen ajax request\n          window.addMsgListener(function(_event){\n              _doSendRequest(_doParseJSON(_event.data));\n          });\n      })();\n    </script>\n  </head>\n  <body></body>\n</html>"
  },
  {
    "path": "res/src/nej_proxy_upload.html",
    "content": "<html><body>\n<!-- 将上传结果序列化为JSON串后填入result中即可 -->\n<script>\n    window.result = '{\"url\":\"http://192.168.146.84:1122/xhr/3.jpg\"}';\n</script>\n<script>\n    var _result = 'NEJ-UPLOAD-RESULT:{\"key\":\"'+window.name+'\",\"result\":\"'+encodeURIComponent(result)+'\"}';\n    if (window.postMessage){\n        parent.postMessage(_result,'*');\n    }else{\n        _result = '\"'+_result.replace(/\"/g,'\\\\\"')+'\"';\n        parent.name = escape('MSG|data='+encodeURIComponent(_result));\n    }\n</script>\n</body></html>"
  },
  {
    "path": "src/base/.dep",
    "content": "基础库依赖关系\n\nglobal    <-    klass\n          <-    platform\n          <-    config      <-    constant\n          <-    util        <-    element    <->    event"
  },
  {
    "path": "src/base/chain.js",
    "content": "/*\n * ------------------------------------------\n * 可链式接口实现代理文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @namespace CHAINABLE */\n/** @module base/chain */\nNEJ.define([\n    'base/util'\n],function(_u,_p){\n    var _cache = {};\n    /**\n     * 添加可链式调用的接口\n     *\n     * 添加可链式接口\n     * ```javascript\n     * NEJ.define([\n     *     'base/chain'\n     * ],function(_l){\n     *     var _map = {};\n     *\n     *      _map._$api1 = function(){\n     *          // TODO\n     *      }\n     *      \n     *      _map._$api2 = function(){\n     *          // TODO\n     *      }\n     * \n     *     _l._$merge(_map);\n     * });\n     * ```\n     *\n     * 使用链式调用接口\n     * ```javascript\n     * NEJ.define([\n     *     '/path/to/api.js',\n     *     'util/chain/chainable'\n     * ],function(_x,$){\n     *     // 使用链式调用api\n     *     $('body > p')._$api1()._$api2();\n     * });\n     * ```\n     * \n     * @method module:base/chain._$merge\n     * @param  {Object} arg0 - 接口集合\n     * @return {Void}\n     */\n    _p._$merge = function(_map){\n        _u._$merge(_cache,_map);\n    };\n    /**\n     * 导出链式接口列表\n     * \n     * @method module:base/chain._$dump\n     * @return {Object} 链式接口列表\n     */\n    _p._$dump = function(){\n        return _cache;\n    };\n    /**\n     * 清除链式列表\n     * \n     * @method module:base/chain._$clear\n     * @return {Void}\n     */\n    _p._$clear = function(){\n        _cache = {};\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/base/config.js",
    "content": "/*\n * ------------------------------------------\n * 平台配置信息\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module base/config */\nNEJ.define([\n    './global.js',\n    '{platform}config.js'\n],function(NEJ,_h,_p,_o,_f,_r){\n    /**\n     * 取Frame跨域Ajax代理文件，通过NEJ_CONF的p_frame配置给定域名的代理文件地址\n     *\n     * @method module:base/config._$getFrameProxy\n     * @see    module:base/config._$get\n     * @param  {String} arg0 - 请求地址或者域名\n     * @return {String}        代理文件地址\n     */\n    _p._$getFrameProxy = function(_url){\n        var _host = _h.__url2host(_url);\n        return _p._$get('frames')[_host]||\n              (_host+'/res/nej_proxy_frame.html');\n    };\n    /**\n     * 取Flash跨域Ajax配置文件，通过NEJ_CONF的p_flash配置给定域名的代理文件地址\n     *\n     * @method module:base/config._$getFlashProxy\n     * @see    module:base/config._$get\n     * @param  {String} arg0 - 请求地址或者域名\n     * @return {String}        代理文件地址\n     */\n    _p._$getFlashProxy = function(_url){\n        return _p._$get('flashs')[_h.__url2host(_url)];\n    };\n    /**\n     * 获取NEJ配置信息，通过NEJ_CONF配置相关信息\n     *\n     * ```javascript\n     *  window.NEJ_CONF = {\n     *      // resource root\n     *      // defalut value -> '/res/'\n     *      root : '/nej/'\n     *      // blank image for ie6-ie7\n     *      // default value -> $root+'nej_blank.gif'\n     *      blank : '/res/nej_blank.gif'\n     *      // localstorage flash\n     *      // default value -> $root+'nej_storage.swf'\n     *      storage : '/res/nej_storage.swf'\n     *      // audio player flash\n     *      // default value -> $root+'nej_player_audio.swf'\n     *      audio : '/res/nej_player_audio.swf'\n     *      // video player flash\n     *      // default value -> $root+'nej_player_video.swf'\n     *      video : '/res/nej_player_video.swf'\n     *      // clipboard flash\n     *      // default value -> $root+'nej_clipboard.swf'\n     *      clipboard : '/res/nej_clipboard.swf'\n     *      // https request proxy\n     *      // default value -> $root+'nej_proxy_flash.swf'\n     *      ajax : '/res/nej_proxy_flash.swf'\n     *      // portrait root\n     *      // default value -> $root+'portrait/'\n     *      portrait : '/res/portrait/'\n     *      // cross domain xhr request for ie6-ie9\n     *      // if path not start with http[s]://\n     *      // will use /res/nej_proxy_frame.html as default\n     *      p_frame:['http://c.d.com/html/nej_proxy_frame.html']\n     *      // flash crossdomain.xml file path\n     *      // default value -> http://a.b.com/crossdomain.xml\n     *      p_flash:['http://a.b.com/proxy/crossdomain.xml']\n     *      // CSRF cookie name and parameter name\n     *      // set p_csrf:true to use URS config {cookie:'AntiCSRF',param:'AntiCSRF'}\n     *      // default value -> {cookie:'',param:''}\n     *      p_csrf:{cookie:'AntiCSRF',param:'AntiCSRF'}\n     *  };\n     * ```\n     *\n     * 配置标识支持\n     *\n     * | 标识                          | 说明 |\n     * | :--              | :-- |\n     * | portrait         | 表情根路径 |\n     * | blank.png        | 空白图片文件地址 |\n     * | ajax.swf         | Ajax代理Flash文件地址 |\n     * | chart.swf        | 图标Flash文件地址 |\n     * | audio.swf        | 实现Audio功能的Flash文件地址 |\n     * | video.swf        | 实现Video功能的Flash文件地址 |\n     * | clipboard.swf    | 实现剪切板功能的Flash文件地址 |\n     * | upload.image.swf | 实现图片上传功能的Flash文件地址 |\n     * | storage.swf      | 实现本地存储功能的Flash文件地址 |\n     *\n     * @method module:base/config._$get\n     * @param  {String}   arg0 - 配置标识\n     * @return {Variable}        配置信息\n     */\n    _p._$get = function(_key){\n        return _h.__get(_key);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.c'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/base/constant.js",
    "content": "/*\n * ------------------------------------------\n * 常量定义文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module base/constant */\nNEJ.define([\n    './global.js',\n    './config.js'\n],function(NEJ,_c,_p,_o,_f,_r){\n    var _seed = +new Date;\n    /**\n     * 找不到指定内容的错误码\n     *\n     * @const {Number} module:base/constant._$CODE_NOTFUND\n     */\n    _p._$CODE_NOTFUND = 10000-_seed;\n    /**\n     * 需要指定的参数未指定的错误码\n     *\n     * @const {Number} module:base/constant._$CODE_NOTASGN\n     */\n    _p._$CODE_NOTASGN = 10001-_seed;\n    /**\n     * 不支持操作的错误码\n     *\n     * @const {Number} module:base/constant._$CODE_NOTSPOT\n     */\n    _p._$CODE_NOTSPOT = 10002-_seed;\n    /**\n     * 操作超时的错误码\n     *\n     * @const {Number} module:base/constant._$CODE_TIMEOUT\n     */\n    _p._$CODE_TIMEOUT = 10003-_seed;\n    /**\n     * 字符串作为脚本执行异常的错误码\n     *\n     * @const {Number} module:base/constant._$CODE_ERREVAL\n     */\n    _p._$CODE_ERREVAL = 10004-_seed;\n    /**\n     * 回调执行异常的错误码\n     *\n     * @const {Number} module:base/constant._$CODE_ERRCABK\n     */\n    _p._$CODE_ERRCABK = 10005-_seed;\n    /**\n     * 服务器返回异常的错误码\n     *\n     * @const {Number} module:base/constant._$CODE_ERRSERV\n     */\n    _p._$CODE_ERRSERV = 10006-_seed;\n    /**\n     * 异常终止的错误码\n     *\n     * @const {Number} module:base/constant._$CODE_ERRABRT\n     */\n    _p._$CODE_ERRABRT = 10007-_seed;\n    /**\n     * 请求头content-type统一名称\n     *\n     * @const {Number} module:base/constant._$HEAD_CT\n     */\n    _p._$HEAD_CT      = 'Content-Type';\n    /**\n     * 文本请求头content-type值\n     *\n     * @const {String} module:base/constant._$HEAD_CT_PLAN\n     */\n    _p._$HEAD_CT_PLAN = 'text/plain';\n    /**\n     * 文件请求头content-type值\n     *\n     * @const {String} module:base/constant._$HEAD_CT_FILE\n     */\n    _p._$HEAD_CT_FILE = 'multipart/form-data';\n    /**\n     * 表单请求头content-type值\n     *\n     * @const {String} module:base/constant._$HEAD_CT_FORM\n     */\n    _p._$HEAD_CT_FORM = 'application/x-www-form-urlencoded';\n    /**\n     * 空图片BASE64编码地址，低版本浏览器使用图片地址\n     *\n     * @const {String} module:base/constant._$BLANK_IMAGE\n     */\n    _p._$BLANK_IMAGE  = _c._$get('blank.png')||'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.g'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/base/demo/define/a.css",
    "content": ".a{color:#f00;}\n.b{color:#0000FF;}"
  },
  {
    "path": "src/base/demo/define/a.js",
    "content": "console.log('aaaaa');\n"
  },
  {
    "path": "src/base/demo/define/a.json",
    "content": "{\n    \"a\":\"aaaaaaaaa\",\n    \"b\":\"bbbbbbbbbb\"\n}\n"
  },
  {
    "path": "src/base/demo/define/define.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>define demo</title>\n    <meta charset=\"utf-8\" />\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n      <script src=\"../../../define.js?pro=/base/demo/define/&abc=/base/demo/\"></script>\n  </head>\n  <body>\n\n    <script>\n      define([\n          'pro/a',\n          'base/element',\n          'json!abc/define/a.json',\n          'res!./a/b/c.swf',\n          'res!/a/c.swf'\n      ],function(a,e,json,swf,xx){\n          log('a:'+json.a);\n          log(swf);\n          log(xx);\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/base/demo/define/style.html",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n        <title>define demo</title>\n        <meta charset=\"utf-8\" />\n        <script>\n            function log(m){\n                var p = document.createElement('p');\n                p.innerHTML = m;\n                document.body.appendChild(p);\n            }\n        </script>\n        <script src=\"../../../define.js?pro=/base/demo/define/&abc=/base/demo/\"></script>\n    </head>\n    <body>\n        <p class=\"a\">aaaaaaaaaaaaaaaa</p>\n        <p class=\"b\">bbbbbbbbbbbbbbbbbbbbbbbbbb</p>\n        <script>\n            define([\n                'css!./a.css'\n            ],function(a){\n                log('a:'+a);\n            });\n        </script>\n    </body>\n</html>"
  },
  {
    "path": "src/base/demo/element.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>element demo</title>\n    <meta charset=\"utf-8\" />\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n  </head>\n  <body>\n    \n    <script src=\"../../define.js\"></script>\n    <script>\n      NEJ.define([\n          'base/element'\n      ],function(_e){\n          // create element and get by id\n          var _div = _e._$create('div');\n          _div.innerHTML = '<p id=\"a\">aaaa</p>';\n          log(_e._$get('a'));\n          // get element after set element id in memory\n          var _div = document.createElement('div');\n          var _id = _e._$id(_div);\n          log(_e._$get(_id));\n          // parse element\n          log(_e._$html2node('<TR><td>col1</td><td>col2</td></TR>'));\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/base/demo/event.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>element demo</title>\n    <meta charset=\"utf-8\" />\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n  </head>\n  <body>\n    <div>\n        <p id=\"abc\">aaaaaaaaaaaaa</p>\n    </div>\n    <input type=\"button\" value=\"aaaa\" onclick=\"document.title=+new Date;\"/>\n    <textarea id=\"abcd\"></textarea>\n    <input type=\"button\" value=\"add\" id=\"btn-add\"/>\n    <input type=\"button\" value=\"del\" id=\"btn-del\"/>\n    <script src=\"../../define.js\"></script>\n    <script>\n      NEJ.define([\n          'base/event',\n          'base/element'\n      ],function(_v,_e){\n//          _v._$addEvent(\n//              document,'click',function(event){\n//                  log('document '+(this==document));\n//              }\n//          );\n//          _v._$addEvent(\n//              document.body,'click',function(event){\n//                  log('body '+(this==document.body));\n//              }\n//          );\n//          _v._$addEvent(\n//              'abc','click',function(event){\n//                  log('abc '+(this.id=='abc'));\n//              }\n//          );\n//          _v._$addEvent(\n//              document,'propertychange',function(event){\n//                  console.log(event.propertyName+'->'+document.title);\n//              }\n//          );\n          var tx = _e._$get('abcd');\n          var handler = function(){\n              console.log('input ->'+tx.value);\n          }\n          _v._$addEvent('btn-add','click',function(){\n              document.body.appendChild(tx);\n              _v._$addEvent(tx,'input',handler);\n          });\n          _v._$addEvent('btn-del','click',function(){\n              _v._$delEvent(tx,'input',handler);\n              _e._$removeByEC(tx);\n              tx.value = '';\n          });\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/base/demo/klass.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>klass demo</title>\n    <meta charset=\"utf-8\" />\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n  </head>\n  <body>\n    <script src=\"../../define.js\"></script>\n    <script>\n      NEJ.define([\n          'base/klass',\n          'util/event'\n      ],function(_k,_t,p){\n          p.A = _k._$klass();\n          var pro = p.A._$extend(_t._$$EventTarget);\n          pro.a = function(){\n              log('a in A');\n              this.b();\n          };\n          pro.b = function(){\n              log('b in A');\n          };\n\n          p.B = _k._$klass();\n          var pro = p.B._$extend(p.A);\n          pro.a = function(){\n              this.__super();\n              log('a in B');\n          };\n          pro.b = function(){\n              this.__super();\n              this.c();\n              log('b in B');\n          };\n          pro.c = function(){\n              log('c in B');\n          };\n\n          p.C = _k._$klass();\n          var pro = p.C._$extend(p.B);\n          pro.a = function(){\n              this.__super();\n              log('a in C');\n          };\n          pro.b = function(){\n              this.__super();\n              log('b in C');\n          };\n          pro.c = function(){\n              log('c in C');\n              this.__super();\n          };\n\n\n          var c = p.C._$allocate();\n          c.a();\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/base/demo/test.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <title>klass demo</title>\n    <meta charset=\"utf-8\" />\n    <script>\n        function log(m){\n            var p = document.createElement('p');\n            p.innerHTML = m;\n            document.body.appendChild(p);\n        }\n    </script>\n</head>\n<body>\n<script src=\"../../define.js\"></script>\n<script>\n    NEJ.define([\n        'base/klass',\n        'util/event'\n    ],function(_k,_t,p){\n        var t = +new Date;\n        p.A0 = _k._$klass();\n        pro = p.A0.prototype;\n        for(var i=0;i<1000;i++){\n            pro['a'+i] = function(){\n                console.log('aaaaaaa');\n            };\n        }\n        console.log(+new Date-t);\n        var t = +new Date;\n        for(var i=0;i<100;i++){\n            var name = 'A'+(i+1);\n            p[name] = _k._$klass();\n            var pro = p[name]._$extend(p['A'+i]);\n            for(var j=0;j<1000;j++){\n                pro['a'+j] = (function(last){\n                    return function(){\n                        if (last>=0){\n                            this['a'+last]();\n                        }\n                        this.__super();\n                        console.log('a');\n                    };\n                })(j-1);\n            }\n        }\n        console.log(+new Date-t);\n        console.log(p);\n\n        var t = +new Date;\n        var a = new p.A100();\n        a.a999();\n        console.log(+new Date-t);\n    });\n</script>\n</body>\n</html>"
  },
  {
    "path": "src/base/demo/util.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>util demo</title>\n    <meta charset=\"utf-8\" />\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n  </head>\n  <body>\n    <form id=\"abc\">\n        <input type=\"text\" name=\"a\"/>\n        <select name=\"b\"><option>aaa</option></select>\n    </form>\n    <script src=\"../../define.js\"></script>\n    <script>\n      NEJ.define([\n          'base/element',\n          'base/util'\n      ],function(_e,_u){\n          _u._$forEach(\n              _e._$get('abc').elements,function(e){\n                  log(e.name);\n              }\n          );\n\n          log(_u._$string2object('a=aaa&b=bbbbb%gh','&'));\n          log(_u._$object2string({a:1111,b:2222,c:'%123455555'},'&'));\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/base/element.js",
    "content": "﻿/*\n * ------------------------------------------\n * 节点接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module base/element */\nNEJ.define([\n    './global.js',\n    './constant.js',\n    './util.js',\n    './event.js',\n    './chain.js',\n    '{platform}element.js'\n],function(NEJ,_g,_u,_v,_x,_h,_p,_o,_f,_r){\n    // variables\n    var _y = {},     // chainable methods\n        _cspol,      // css text pool\n        _empol = {}, // elements without id property, eg. document,window\n        _dirty = {}, // temporary element with id\n        _fragment = document.createDocumentFragment(); // node in memory\n    // init\n    if (!document.head){\n         document.head = document.getElementsByTagName('head')[0]||document.body;\n    }\n    // only for test\n    _p.dump = function(){\n        return {\n            pool:_empol,\n            dirty:_dirty,\n            fragment:_fragment\n        };\n    };\n    /**\n     * 为节点设置一个唯一的标识\n     *\n     * 结构举例\n     * ```html\n     *    <div id=\"abc\">aaaaa</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 如果有id，返回原来的id,否则返回auto-id-12345678(8位随机字符串)\n     *       var _id = _e._$id(_node||\"abc\");\n     *   });\n     * ```\n     *\n     * @method module:base/element._$id\n     * @param  {String|Node} arg0 - 节点标识或者对象\n     * @return {String}             节点标识\n     */\n    /**\n     * @method CHAINABLE._$id\n     * @see module:base/element._$id\n     */\n    _p._$id =\n    _y._$id = function(_element){\n        _element = _p._$get(_element);\n        if (!_element) return;\n        var _id = !!_element.id ? _element.id\n                : 'auto-id-'+_u._$uniqueID();\n        if (!('id' in _element)){\n            _empol[_id] = _element;\n        }\n        _element.id = _id;\n        // check if element can be getted\n        if (!_p._$get(_id)){\n            _dirty[_id] = _element;\n        }\n        return _id;\n    };\n    /**\n     * 根据标识取节点对象，包括在内存中的节点\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 先根据id从内存中取，再从页面取\n     *       var _node = _e._$get(\"abc\");\n     *   });\n     * ```\n     *\n     * @method module:base/element._$get\n     * @param  {String|Node} arg0 - 节点标识或者对象\n     * @return {Node}               节点对象\n     */\n    _p._$get = function(_element){\n        // for document/window\n        // fix dirty window object in mac safari\n        try{\n            var _node = _empol[''+_element];\n        }catch(ex){\n            // ignore\n        }\n        if (!!_node){\n            return _node;\n        }\n        // element is node\n        if (!_u._$isString(_element)&&\n            !_u._$isNumber(_element)){\n            return _element;\n        }\n        // element is id\n        // check node in page first\n        var _node = document.getElementById(_element);\n        if (!_node){\n            _node = _h.__getElementById(_fragment,_element);\n        }\n        // remove dirty element\n        if (!!_node){\n            delete _dirty[_element];\n        }\n        return _node||_dirty[_element];\n    };\n    /**\n     * 取节点的子节点列表\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">\n     *       <p>1</p>\n     *       <p><span>2</span></p>\n     *       <p>3</p>\n     *   </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 取直接的3个子节点(p标签)\n     *       var _childs = _e._$getChildren('abc');\n     *\n     *       // 使用类名过滤，去带a或者b样式类的子节点\n     *       var _childs = _e._$getChildren('abc','a b');\n     *   });\n     * ```\n     *\n     * @method module:base/element._$getChildren\n     * @param  {String|Node} arg0 - 节点标识或者对象\n     * @param  {String}      arg1 - 样式标识\n     * @return {Array}              子节点列表\n     */\n    /**\n     * @method CHAINABLE._$getChildren\n     * @see module:base/element._$getChildren\n     */\n    _p._$getChildren =\n    _y._$getChildren = function(_element,_clazz){\n        _element = _p._$get(_element);\n        if (!_element) return null;\n        var _list = _h.__getChildren(_element);\n        if (!!_clazz){\n            _u._$reverseEach(\n                _list,function(_node,_index,_list){\n                    if (!_p._$hasClassName(_node,_clazz)){\n                        _list.splice(_index,1);\n                    }\n                }\n            );\n        }\n        return _list;\n    };\n    /**\n     * 根据过滤条件取第一个满足条件的父节点\n     *\n     * 结构举例\n     * ```html\n     *   <div data-a=\"aaa\">\n     *       <p>1</p>\n     *       <div a=\"aaaaaa\">\n     *           <p class=\"a\">\n     *               <span id=\"abc\">2</span>\n     *           </p>\n     *       </div>\n     *       <p>3</p>\n     *   </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 返回包含样式a的节点 <p class=\"a\">\n     *       var node = _e._$getParent('abc','c:a');\n     *\n     *       // 返回包含属性a的节点 <div a=\"aaaaaa\">\n     *       var node = _e._$getParent('abc','a:a')\n     *\n     *       // 返回包含data属性a的节点 <div data-a=\"aaa\">\n     *       var node = _e._$getParent('abc','d:a');\n     *\n     *       // 返回标签为p的节点 <p class=\"a\">\n     *       var node = _e._$getParent('abc','t:p');\n     *\n     *       // 返回符合过滤条件的父节点\n     *       var node = _e._$getParent('abc',function(_element){\n     *           return _element.scrollHeight>_element.clientHeight;\n     *       });\n     *   });\n     * ```\n     *\n     * @method module:base/element._$getChildren\n     * @param  {String|Node}      arg0 - 节点标识或者对象\n     * @param  {String|Function}  arg1 - 过滤规则\n     * @return {Node}             父节点\n     */\n    _p._$getParent = (function(){\n        var _exmap;\n        var _doFilter = function(_name,_element){\n            var _arr = _name.split(':');\n            if (_arr.length>1){\n                if (!_exmap){\n                    _exmap = {\n                        a:_p._$attr,\n                        d:_p._$dataset,\n                        c:_p._$hasClassName,\n                        t:function(n,v){return (n.tagName||'').toLowerCase()===v;}\n                    };\n                }\n                var _check = _exmap[_arr[0]];\n                if (!!_check){\n                    return !!_check(_element,_arr[1]);\n                }\n                _name = _arr[1];\n            }\n            return !!_p._$attr(_element,_name)||\n                   !!_p._$dataset(_element,_name)||\n                     _p._$hasClassName(_element,_name);\n        };\n        return function(_element,_filter){\n            _element = _p._$get(_element);\n            if (!_element){\n                return;\n            }\n            if (!_filter){\n                return _element;\n            }\n            if (_u._$isString(_filter)){\n                _filter = _doFilter._$bind(null,_filter);\n            }\n            if (_u._$isFunction(_filter)){\n                while(_element){\n                    if (!!_filter(_element)){\n                        return _element;\n                    }\n                    _element = _element.parentNode;\n                }\n                return null;\n            }\n            return _element;\n        };\n    })();\n    /**\n     * 根据类名取节点列表\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">\n     *     <p class=\"item\">1</p>\n     *     <div><p class=\"item\">2</p></div>\n     *     <p class=\"item\">3</p>\n     *   </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 获取abc节点下样式带有\"item\"的节点列表,如果没有父节点，返回null\n     *       var _list = _e._$getByClassName('abc','item');\n     *   });\n     * ```\n     *\n     * @method module:base/element._$getByClassName\n     * @param  {String|Node} arg0 - 节点标识或者对象\n     * @param  {String}      arg1 - 类名\n     * @return {Array}              节点列表\n     */\n    /**\n     * @method CHAINABLE._$getByClassName\n     * @see module:base/element._$getByClassName\n     */\n    _p._$getByClassName =\n    _y._$getByClassName = function(_element,_class){\n        _element = _p._$get(_element);\n        return !_element ? null :\n                _h.__getElementsByClassName(\n                    _element,_class.trim()\n                );\n    };\n    /**\n     * 根据从兄弟节点中搜索符合条件的节点\n     *\n     * 结构举例\n     * ```html\n     *   <div>\n     *     <p class=\"item\" id=\"a1\">1</p>\n     *     <p class=\"item\" id=\"a2\">2</p>\n     *     <p class=\"item\" id=\"a3\">3</p>\n     *   </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 取a2的后一个兄弟节点a3\n     *       var _node = _e._$getSibling('a2');\n     *\n     *       // 取a2的前一个兄弟节点a1\n     *       var _node = _e._$getSibling('a2',{backward:true});\n     *\n     *       // 过滤搜索，从a2向后搜索找id为a4的节点\n     *       var _node = _e._$getSibling('a2',function(_element){\n     *           return _element.id=='a4'\n     *       });\n     *\n     *       // 过滤搜索，从a2向前搜索找id为a0的节点\n     *       var _node = _e._$getSibling('a2',{\n     *           backward:true,\n     *           filter:function(_element){\n     *               return _element.id=='a0'\n     *           }\n     *       });\n     *   });\n     * ```\n     *\n     * @method   module:base/element._$getSibling\n     * @param    {String|Node}     arg0     - 节点标识或者对象\n     * @param    {Function|Object} arg1     - 如果是函数则表示过滤器，否则为配置信息\n     * @property {Boolean}         backward - 是否后向搜索，默认前向搜索\n     * @property {Function}        filter   - 节点过滤器，返回true表示需要返回的节点，找到第一个即返回\n     * @return   {Node}                       符合条件的节点\n     */\n    /**\n     * @method CHAINABLE._$getSibling\n     * @see module:base/element._$getSibling\n     */\n    _p._$getSibling =\n    _y._$getSibling = (function(){\n        var _doFilter = function(){\n            return !0;\n        };\n        return function(_element,_filter){\n            _element = _p._$get(_element);\n            if (!_element){\n                return null;\n            }\n            var _conf = {\n                backward:!1,\n                filter:_doFilter\n            };\n            if (_u._$isFunction(_filter)){\n                _conf.filter = _filter;\n            }else{\n                _conf = _u._$fetch(_conf,_filter);\n            }\n            var _next = _conf.backward\n                      ? _h.__previousSibling\n                      : _h.__nextSibling;\n            while(_element=_next(_element)){\n                if (_conf.filter(_element)){\n                    break;\n                }\n            }\n            return _element;\n        };\n    })();\n    /**\n     * 取节点所在的滚动容器，\n     * 从当前节点开始往上遍历，直到出现滚动条的节点\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"efg\">\n     *     <div id=\"abc\">123</div>\n     *   </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 加入efg节点出现滚动条，则这里找到的是efg节点\n     *       var _sbody = _e._$getScrollViewPort('abc');\n     *\n     *       // 不带任何参数取页面滚动条所在节点\n     *       var _sbody = _e._$getScrollViewPort();\n     *   });\n     * ```\n     *\n     * @method module:base/element._$getScrollViewPort\n     * @param  {String|Node} arg0 - 节点标识或者对象\n     * @return {Node}               视窗节点\n     */\n    _p._$getScrollViewPort = function(_element){\n        _element = _p._$get(_element);\n        if (!!_element){\n            _element = _element.parentNode;\n            while(!!_element){\n                if (_element.scrollHeight>\n                    _element.clientHeight){\n                    break;\n                }\n                _element = _element.parentNode;\n            }\n            if (!!_element){\n                return _element;\n            }\n        }\n        var _tmp1 = document.body.scrollHeight,\n            _tmp2 = document.documentElement.scrollHeight;\n        return _tmp2>=_tmp1?document.documentElement:document.body;\n    };\n    /**\n     * 盒模型结构\n     *\n     * @typedef  {Object} module:base/element~BoxModel\n     * @property {Number} scrollTop    - 滚动垂直偏移\n     * @property {Number} scrollLeft   - 滚动水平偏移\n     * @property {Number} clientWidth  - 页面可视宽度\n     * @property {Number} clientHeight - 页面可视高度\n     * @property {Number} scrollWidth  - 页面滚动宽度\n     * @property {Number} scrollHeight - 页面滚动高度\n     */\n    /**\n     * 取页面盒信息，返回盒信息内容：\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 返回信息见说明\n     *       var _box = _e._$getPageBox();\n     *   });\n     * ```\n     *\n     * @method module:base/element._$getPageBox\n     * @param  {Document} arg0 - 文档对象\n     * @return {module:base/element~BoxModel} 盒信息\n     */\n    _p._$getPageBox = (function(){\n        // get min value but not zero\n        var _getClientBox = function(_list){\n            var _result = 0;\n            _u._$forEach(\n                _list,function(_size){\n                    if (!_size) return;\n                    if (!_result){\n                        _result = _size;\n                    }else{\n                        _result = Math.min(_result,_size);\n                    }\n                }\n            );\n            return _result;\n        };\n        var _farr = [\n            {\n                main:'scroll',\n                sub:['Top','Left'],\n                func:function(_key,_body0,_body1){\n                    return Math.max(\n                        _body0['scroll'+_key],\n                        _body1['scroll'+_key]\n                    );\n                }\n            },\n            {\n                main:'client',\n                sub:['Width','Height'],\n                func:function(_key,_body0,_body1){\n                    return _getClientBox([\n                        _body0['client'+_key],\n                        _body0['offset'+_key],\n                        _body1['client'+_key],\n                        _body1['offset'+_key]\n                    ]);\n                }\n            },\n            {\n                main:'scroll',\n                sub:['Width','Height'],\n                func:function(_key,_body0,_body1,_result){\n                    return Math.max(\n                        _result['client'+_key],\n                        _body0['scroll'+_key],\n                        _body1['scroll'+_key]\n                    );\n                }\n            }\n        ];\n        return function(_document){\n            var _result = {},\n                _doc   = _document||document,\n                _body0 = _doc.body,\n                _body1 = _doc.documentElement;\n            _u._$forEach(\n                _farr,function(_item){\n                    var _main = _item.main;\n                    _u._$forEach(\n                        _item.sub,function(_key){\n                            _result[_main+_key] = _item.func(\n                                _key,_body0,_body1,_result\n                            );\n                        }\n                    );\n                }\n            );\n            return _result;\n        };\n    })();\n    /**\n     * 按比例将给定大小缩放至限制区域内\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 限制区域大小 100*10\n     *       var _limit = {width:100,height:10};\n     *\n     *       // 给定200*10的大小，由于宽度超出，缩放后为{width:100,height:5}\n     *       var _box = _e._$getMaxBox({width:200,height:10},_limit);\n     *\n     *       // 给定100*20的大小，由于高度超出，缩放后为{width:50,height:10}\n     *       var _box = _e._$getMaxBox({width:100,height:20},_limit);\n     *\n     *       // 给定 50*5，没有超出限制，返回{width:50,height:5}\n     *       var _box = _e._$getMaxBox({width:50,height:5},_limit);\n     *   });\n     * ```\n     *\n     * @method   module:base/element._$getMaxBox\n     * @param    {module:base/element~SizeModel} arg0 - 原始大小\n     * @param    {module:base/element~SizeModel} arg1 - 最大限制大小\n     * @return   {module:base/element~SizeModel}        按比例计算出的最大值信息\n     */\n    _p._$getMaxBox = function(_org,_max){\n        var _result = _u._$merge({},_org),\n            _mrto = _max.width/_max.height,\n            _orto = _org.width/_org.height;\n        // height overflow\n        if (_mrto>_orto&&\n            _org.height>_max.height){\n            _result.height = _max.height;\n            _result.width = _result.height*_orto;\n        }\n        // width overflow\n        if (_mrto<_orto&&\n            _org.width>_max.width){\n            _result.width = _max.width;\n            _result.height = _result.width/_orto;\n        }\n        return _result;\n    };\n    /**\n     * 滚动到指定节点\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"a\" style=\"padding:5px 0 0 10px;\"></div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 滚动到页面上a这节点的位置\n     *       _e._$scrollTo('a');\n     *   });\n     * ```\n     *\n     * @method module:base/element._$scrollTo\n     * @param  {Node|String} arg0 - 节点\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$scrollTo\n     * @see module:base/element._$scrollTo\n     */\n    _p._$scrollTo =\n    _y._$scrollTo = function(_element){\n        var _offset = _p._$offset(_element);\n        window.scrollTo(_offset.x,_offset.y);\n    };\n    /**\n     * 大小信息对象\n     * @typedef  {Object} module:base/element~SizeModel\n     * @property {Number} width  - 宽度\n     * @property {Number} height - 高度\n     */\n    /**\n     * 位置信息对象\n     * @typedef  {Object} module:base/element~PositionModel\n     * @property {Number} top  - 垂直位置\n     * @property {Number} left - 水平位置\n     */\n    /**\n     * 计算在容器中对齐时的位置信息\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 容器大小\n     *       var _box = {width:100,height:40};\n     *\n     *       // 默认居中对齐返回 {top:15,left:40}\n     *       var _pos = _e._$align(_box,{width:20,height:10});\n     *\n     *       // 左下对齐返回 {top:30,left:0}\n     *       var _pos = _e._$align(_box,{width:20,height:10},'left bottom');\n     *   });\n     * ```\n     *\n     * @method module:base/element._$align\n     * @param  {module:base/element~SizeModel} arg0 - 容器大小\n     * @param  {module:base/element~SizeModel} arg1 - 原始大小\n     * @param  {String} arg2 - 对齐方式，水平+空格+垂直，如left top，默认为 center middle，\n     *                         水平：left/center/right，\n     *                         垂直：top/middle/bottom\n     * @return {module:base/element~PositionModel} 位置信息\n     */\n    _p._$align = (function(){\n        var _reg = /\\s+/;\n        var _fmap = {\n            left:function(){\n                return 0;\n            },\n            center:function(_box,_org){\n                return (_box.width-_org.width)/2;\n            },\n            right:function(_box,_org){\n                return _box.width-_org.width;\n            },\n            top:function(){\n                return 0;\n            },\n            middle:function(_box,_org){\n                return (_box.height-_org.height)/2;\n            },\n            bottom:function(_box,_org){\n                return _box.height-_org.height;\n            }\n        };\n        return function(_box,_org,_align){\n            var _result = {},\n                _arr  = (_align||'').split(_reg),\n                _top  = _fmap[_arr[1]]||_fmap.middle,\n                _left = _fmap[_arr[0]]||_fmap.center;\n            _result.top = _top(_box,_org);\n            _result.left = _left(_box,_org);\n            return _result;\n        };\n    })();\n    /**\n     * 计算两个节点之间的偏移量\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"a\" style=\"position:relative;padding:5px 0 0 10px;\">\n     *     <span id=\"b\">123</span>\n     *   </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 计算节点b到节点a(外层需要定位属性)的距离，如果没有指定节点，默认计算的根节点\n     *       // _result : {x:10,y:5}\n     *       var _result = _e._$offset('b','a');\n     *   });\n     * ```\n     *\n     * @method module:base/element._$offset\n     * @param  {String|Node} arg0 - 起始节点\n     * @param  {String|Node} arg1 - 结束节点，没有该参数则计算到根节点\n     * @return {Object}             偏移量，如{x:234,y:987}\n     */\n    /**\n     * @method CHAINABLE._$offset\n     * @see module:base/element._$offset\n     */\n    _p._$offset =\n    _y._$offset = (function(){\n        var _isRoot = function(_element){\n            return _element==document.body||\n                   _element==document.documentElement;\n        };\n        return function(_from,_to){\n            _from = _p._$get(_from);\n            if (!_from){\n                return null;\n            }\n            _to = _p._$get(_to)||null;\n            var _node = _from,\n                _result = {x:0,y:0},\n                _isroot,_delta,_border;\n            while(!!_node&&_node!=_to){\n                _isroot = _isRoot(_node)||_node==_from;\n                _delta = _isroot?0:_node.scrollLeft;\n                _border = parseInt(_p._$getStyle(_node,'borderLeftWidth'))||0;\n                _result.x += _node.offsetLeft+_border-_delta;\n                _delta = _isroot?0:_node.scrollTop;\n                _border = parseInt(_p._$getStyle(_node,'borderTopWidth'))||0;\n                _result.y += _node.offsetTop+_border-_delta;\n                _node = _node.offsetParent;\n            }\n            return _result;\n        };\n    })();\n    /**\n     * 节点占全屏\n     *\n     * @method module:base/element._$fullScreen\n     * @param  {Node} arg0 - 节点\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$fullScreen\n     * @see module:base/element._$fullScreen\n     */\n    _p._$fullScreen =\n    _y._$fullScreen = function(_element){\n        _element = _p._$get(_element);\n        if (!!_element){\n            _h.__fullScreen(\n                _element,\n                _p._$getPageBox()\n            );\n        }\n    };\n    /**\n     * 为节点增加用于盖select/flash等控件的层\n     *\n     * @method module:base/element._$mask\n     * @see    module:base/element._$unmask\n     * @param  {Node} arg0 - 节点\n     * @return {Node}        盖层节点\n     */\n    /**\n     * @method CHAINABLE._$mask\n     * @see module:base/element._$mask\n     */\n    _p._$mask =\n    _y._$mask = function(_element){\n        _element = _p._$get(_element);\n        if (!!_element){\n            _p._$id(_element);\n            return _h.__mask(_element);\n        }\n        return null;\n    };\n    /**\n     * 为节点移除用于盖select/flash等控件的层\n     *\n     * @method module:base/element._$unmask\n     * @see    module:base/element._$mask\n     * @param  {Node} arg0 - 节点\n     * @return {Node}        盖层节点\n     */\n    /**\n     * @method CHAINABLE._$unmask\n     * @see module:base/element._$unmask\n     */\n    _p._$unmask =\n    _y._$unmask = function(_element){\n        _element = _p._$get(_element);\n        if (!!_element){\n            _p._$id(_element);\n            return _h.__unmask(_element);\n        }\n        return null;\n    };\n    /**\n     * 创建节点，使用该接口创建的结构后续可通过_$get接口根据ID取到节点\n     *\n     * 结构举例\n     * ```javascript\n     *   <div id=\"abc\">1</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 创建一个节点，挂到body上\n     *       _e._$create(\"div\",\"m-body\",document.body);\n     *\n     *       // 创建一个节点挂到id是abc的节点上\n     *       // 结果：<div id=\"abc\">1<p class=\"m-list\"></p></div>\n     *       _e._$create(\"p\",\"m-list\",\"abc\");\n     * \n     *       // 创建一个节点放在内存中\n     *       var _node = _e._$create('div');\n     *       _node.innerHTML = '<p id=\"a\">aaaaaa</p><p id=\"b\">bbbbbb</p>';\n     *       // 后续可以通过id取id为a的节点\n     *       var _pa = _e._$get('a');\n     *   });\n     * ```\n     *\n     * @method module:base/element._$create\n     * @param  {String}      arg0 - 标签\n     * @param  {String}      arg1 - 样式\n     * @param  {String|Node} arg2 - 父节点标识或者对象\n     * @return {Node}               节点\n     */\n    _p._$create = (function(){\n        var _map = {\n            a:{href:'#',hideFocus:!0},\n            style:{type:'text/css'},\n            link:{type:'text/css',rel:'stylesheet'},\n            iframe:{frameBorder:0},\n            script:{defer:!0,type:'text/javascript'}\n        };\n        return function(_tag,_class,_parent){\n            var _element = document.createElement(_tag),\n                _config = _map[_tag.toLowerCase()];\n            _u._$merge(_element,_config);\n            if (!!_class) _element.className = _class;\n            _parent = _p._$get(_parent);\n            if (!!_parent){\n                _parent.appendChild(_element);\n            }else{\n                // append to documentfragment for get by id\n                if (!_config){\n                    _fragment.appendChild(_element);\n                }\n            }\n            return _element;\n        };\n    })();\n    /**\n     * 创建可交互框架\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"frameCnt\"></div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *      var _xFrame = _e._$createXFrame({\n     *          src:'http://www.baidu.com',\n     *          name:'百度',\n     *          parent:'frameCnt',\n     *          visible:false,\n     *          onload:function(){\n     *              // 加载frame成功后，name设置成功，为百度\n     *              // 加载frame成功后，显示效果正确，display:none\n     *          }\n     *      });\n     *   });\n     * ```\n     *\n     * @method   module:base/element._$createXFrame\n     * @param    {Object}               arg0    - 可选配置参数\n     * @property {String}               src     - 框架地址\n     * @property {String}               name    - 框架名称\n     * @property {String|Node|Function} parent  - 父节点或者框架加入父容器的执行函数\n     * @property {Boolean}              visible - 是否可见\n     * @property {Function}             onload  - 框架载入回调\n     * @return {Node}                             框架节点\n     */\n    _p._$createXFrame = (function(){\n        var _getFrameSrc = function(){\n            if (location.hostname==document.domain){\n                return 'about:blank';\n            }\n            return 'javascript:(function(){document.open();document.domain=\"'+document.domain+'\";document.close();})();';\n        };\n        var _getFrameWithName = function(_name){\n            _name = _name.trim();\n            if (!_name){\n                return _p._$create('iframe');\n            }\n            // pass name to frame\n            var _iframe;\n            try{\n                _iframe = document.createElement(\n                          '<iframe name=\"'+_name+'\"></iframe>');\n                _iframe.frameBorder = 0;\n            }catch(e){\n                _iframe = _p._$create('iframe');\n                _iframe.name = _name;\n            }\n            return _iframe;\n        };\n        return function(_options){\n            _options = _options||_o;\n            var _iframe = _getFrameWithName(_options.name||'');\n            if (!_options.visible){\n                _iframe.style.display = 'none';\n            }\n            if (_u._$isFunction(_options.onload)){\n                _v._$addEvent(_iframe,'load',function(_event){\n                    if (!_iframe.src) return;\n                    _v._$clearEvent(_iframe,'load');\n                    _options.onload(_event);\n                });\n            }\n            // will trigger onload\n            var _parent = _options.parent;\n            if (_u._$isFunction(_parent)){\n                try{_parent(_iframe);}catch(e){}\n            }else{\n                (_p._$get(_parent)||document.body).appendChild(_iframe);\n            }\n            // ensure trigger onload async\n            var _src = _options.src||_getFrameSrc();\n            window.setTimeout(function(){\n                _iframe.src = _src;\n            },0);\n            return _iframe;\n        };\n    })();\n    /**\n     * 删除节点\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 移除节点前先清理节点上的事件\n     *       _e._$remove('abc',false);\n     *       // 移除节点前不清理节点上的事件\n     *       _e._$remove('abc',true);\n     *   });\n     * ```\n     *\n     * @method module:base/element._$remove\n     * @see    module:base/element._$removeByEC\n     * @param  {String|Node} arg0 - 节点标识或者对象\n     * @param  {Boolean}     arg1 - 是否禁止事件清理\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$remove\n     * @see module:base/element._$remove\n     */\n    _p._$remove =\n    _y._$remove = (function(){\n        var _fmap = {\n            img:function(_node){\n                _node.src = _g._$BLANK_IMAGE;\n            },\n            iframe:function(_node){\n                _node.src = 'about:blank';\n            }\n        };\n        var _doClear = function(_node,_tag){\n            if (!_tag){\n                var _xtag = (_node.tagName||'').toLowerCase(),\n                    _func = _fmap[_xtag];\n                if (!!_func){\n                    _func(_node);\n                }\n                return;\n            }\n            if (!!_node.getElementsByTagName){\n                _u._$forEach(\n                    _node.getElementsByTagName(_tag),\n                    _doClear\n                );\n            }\n        };\n        return function(_element){\n            _element = _p._$get(_element);\n            if (!!_element){\n                // clear events\n                if (!arguments[1]){\n                    _v._$clearEvent(_element);\n                }\n                // clear elements\n                _doClear(_element);\n                _doClear(_element,'img');\n                _doClear(_element,'iframe');\n                // remove node\n                if (!!_element.parentNode){\n                    _element.parentNode.removeChild(_element);\n                }\n            }\n        };\n    })();\n    /**\n     * 节点移至内存\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 先生成一个节点加到body下\n     *       var _node = _e._$create('div','js-div',document.body);\n     *       // 把节点移动到内存中\n     *       _e._$removeByEC(_node);\n     *       // 从body上没有取到节点,结果为[]\n     *       _e._$getByClassName(document.body,'js-div');\n     *   });\n     * ```\n     *\n     * @method module:base/element._$removeByEC\n     * @see    module:base/element._$remove\n     * @param  {String|Node} arg0 - 节点标识或者对象\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$removeByEC\n     * @see module:base/element._$removeByEC\n     */\n    _p._$removeByEC =\n    _y._$removeByEC = function(_element){\n        _element = _p._$get(_element);\n        if (!!_element){\n            try{\n                _fragment.appendChild(_element);\n            }catch(ex){\n                // ignore\n                console.error(ex);\n            }\n        }\n    };\n    /**\n     * 清除所有子节点\n     *\n     * 结构举例\n     * ```html\n     *   <ul id=\"abc\">\n     *     <li>aaaaaaaaaaaaa</li>\n     *     <li>bbbbbbbbbbbbb</li>\n     *     <li>ccccccccccccc</li>\n     *   </ul>\n     *\n     *   <table id=\"efg\">\n     *     <tr><td>1111</td><td>1111</td></tr>\n     *     <tr><td>2222</td><td>2222</td></tr>\n     *     <tr><td>3333</td><td>3333</td></tr>\n     *   </table>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 清除ul下的子节点\n     *       _e._$clearChildren('abc');\n     *\n     *       // 清除table下的子节点\n     *       _e._$clearChildren('efg');\n     *   });\n     * ```\n     *\n     * @method module:base/element._$clearChildren\n     * @see    module:base/element._$remove\n     * @param  {String|Node} arg0 - 容器节点\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$clearChildren\n     * @see module:base/element._$clearChildren\n     */\n    _p._$clearChildren =\n    _y._$clearChildren = function(_element){\n        _element = _p._$get(_element);\n        if (!!_element){\n            _u._$reverseEach(\n                _element.childNodes,\n                function(_node){\n                    _p._$remove(_node);\n                }\n            );\n        }\n    };\n    /**\n     * 内联元素增加定位封装\n     *\n     * 结构举例\n     * ```html\n     *   <input type=\"text\" id=\"abc\"/>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 包装定位的span\n     *       _e._$wrapInline('abc');\n     *   });\n     * ```\n     *\n     * 生成结构如下\n     * ```html\n     *   <span style=\"position:relative;zoom:1\">\n     *     <input type=\"text\" id=\"abc\"/>\n     *     <!-- 此api返回以下这个节点 -->\n     *     <span style=\"position:absolute;top:0;left:0;\"></span>\n     *   </span>\n     * ```\n     *\n     * 应用举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 返回容器的样式名称\n     *       // 通过这个样式名称可以取到一个绝对定位的样式名 class+'-show'\n     *       var _node = _e._$wrapInline('abc',{\n     *           tag:'label',\n     *           clazz:'js-xxx'\n     *       });\n     *       // 可以在返回的节点里添加想要显示的结构\n     *       _node.innerHTML = '<span>aaa</span><span>aaa</span>';\n     *   });\n     * ```\n     *\n     * @method   module:base/element._$wrapInline\n     * @param    {String|Node}  arg0  - 内联节点\n     * @param    {Object}       arg1  - 绝对定位节点配置信息\n     * @property {String}       tag   - 标记名称，默认span\n     * @property {String}       nid   - 节点识别样式名，这个会被添加到样式中作为标识\n     * @property {String}       clazz - 样式名称\n     * @return   {Node}                 绝对定位的节点\n     */\n    /**\n     * @method CHAINABLE._$wrapInline\n     * @see module:base/element._$wrapInline\n     */\n    _p._$wrapInline =\n    _y._$wrapInline = (function(){\n        var _clazz,\n            _reg0 = /\\s+/;\n        var _doInitStyle = function(){\n            if (!!_clazz) return;\n            _clazz = _p._$pushCSSText('.#<uispace>{position:relative;zoom:1;}.#<uispace>-show{position:absolute;top:0;left:100%;cursor:text;white-space:nowrap;overflow:hidden;}');\n            _p._$dumpCSSText();\n        };\n        return function(_element,_options){\n            _element = _p._$get(_element);\n            if (!_element){\n                return null;\n            }\n            // init style\n            _doInitStyle();\n            _options = _options||_o;\n            // check relative parent\n            var _parent = _element.parentNode;\n            if (!_p._$hasClassName(_parent,_clazz)){\n                // build wrapper box\n                _parent = _p._$create('span',_clazz);\n                _element.insertAdjacentElement('beforeBegin',_parent);\n                _parent.appendChild(_element);\n            }\n            // check absolute node\n            var _nid = _options.nid||'',\n                _node = _p._$getByClassName(\n                    _parent,_nid||\n                   (_clazz+'-show')\n                )[0];\n            if (!_node){\n                var _klass = ((_options.clazz||'')+' '+_nid).trim();\n                _klass = _clazz+'-show'+(!_klass?'':' ')+_klass;\n                _node = _p._$create(_options.tag||'span',_klass);\n                _parent.appendChild(_node);\n            }\n            // append class to parent node\n            var _klass = _options.clazz;\n            if (!!_klass){\n                _klass = (_klass||'').trim().split(_reg0)[0]+'-parent';\n                _p._$addClassName(_parent,_klass);\n            }\n            return _node;\n        };\n    })();\n    /**\n     * 设置或者获取指定标识的数据\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 设置值操作\n     *       // <div id=\"abc\" data-img=\"http://a.b.com/a.png\">123</div>\n     *       // 返回value值: http://a.b.com/a.png\n     *       var _src = _e._$dataset('abc','img','http://a.b.com/a.png');\n     *       // 取值操作\n     *       var _src = _e._$dataset('abc','img');\n     * \n     *       // 批量设置\n     *       var _map = _e._$dataset('abc',{\n     *           a:'aaaaa',\n     *           b:'bbbbbbbb',\n     *           c:'ccccccccc'\n     *       });\n     * \n     *       // 批量取值\n     *       // 返回：{a:'aaaaa',b:'bbbbbbbb',c:'ccccccccc'}\n     *       var _map = _e._$dataset('abc',['a','b','c']);\n     *   });\n     * ```\n     *\n     * @method module:base/element._$dataset\n     * @see    module:base/element._$attr\n     * @param  {String}              arg0 - 数据标识\n     * @param  {String|Object|Array} arg1 - 属性名\n     * @return {String|Object}              数据值\n     */\n    /**\n     * @method CHAINABLE._$dataset\n     * @see module:base/element._$dataset\n     */\n    _p._$dataset =\n    _y._$dataset = function(_element,_key,_value){\n        // check element\n        var _id = _p._$id(_element);\n        if (!_id){\n            return null;\n        }\n        // check single key-value\n        if (_u._$isString(_key)){\n            return _h.__dataset(\n                _p._$get(_element),\n                _key,_value\n            );\n        }\n        // check map set\n        // ignore argument _value\n        if (_u._$isObject(_key)){\n            var _ret = {};\n            _u._$forIn(_key,function(_v,_k){\n                _ret[_k] = _p._$dataset(_id,_k,_v);\n            });\n            return _ret;\n        }\n        // check array get\n        // ignore argument _value\n        if (_u._$isArray(_key)){\n            var _ret = {};\n            _u._$forEach(_key,function(_k){\n                _ret[_k] = _p._$dataset(_id,_k);\n            });\n            return _ret;\n        }\n        return null;\n    };\n    /**\n     * 取某个节点的属性值\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 设置成 <div id=\"abc\" data-img=\"http://a.b.com/a.png\">123</div>\n     *       // 返回value值: http://a.b.com/a.png\n     *       var _src = _e._$attr('abc','data-img','http://a.b.com/a.png');\n     *\n     *       // 如果设置了img的值返回data-img，否则放回空字符串\n     *       var _src = _e._$attr('abc','data-img');\n     *   });\n     * ```\n     *\n     * @method module:base/element._$attr\n     * @see    module:base/element._$dataset\n     * @param  {String|Node} arg0 - 节点标识或者对象\n     * @param  {String}      arg1 - 属性名称\n     * @param  {String}      arg2 - 属性值，如果没有设置此参数则表示取值\n     * @return {String}             属性值\n     */\n    /**\n     * @method CHAINABLE._$attr\n     * @see module:base/element._$attr\n     */\n    _p._$attr =\n    _y._$attr = function(_element,_name,_value){\n        _element = _p._$get(_element);\n        if (!_element){\n            return '';\n        }\n        if (_value!==undefined&&!!_element.setAttribute){\n            _element.setAttribute(_name,_value);\n        }\n        return _h.__getAttribute(_element,_name);\n    };\n    /**\n     * html代码转节点对象，\n     * 如果转换出来的节点数量超过[包含]2个，\n     * 则最外面增加一个容器节点，即返回的始终是一个节点\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">\n     *     <span>123</span>\n     *   </div>\n     * ```\n     *\n     * 代码举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       var _node = _e._$html2node('<div>1</div><div><span>2</span></div>');\n     *   });\n     * ```\n     *\n     * 返回结果\n     * ```html\n     *   <div> <!-- 返回此节点 -->\n     *     <div>1</div>\n     *     <div><span>2</span></div>\n     *   </div>\n     * ```\n     *\n     * @method module:base/element._$html2node\n     * @param  {String} arg0 - 代码\n     * @return {Node}          节点\n     */\n    _p._$html2node = (function(){\n        var _reg = /<(.*?)(?=\\s|>)/i, // first tag name\n            _tmap = {li:'ul',tr:'tbody',td:'tr',th:'tr',option:'select'};\n        return function(_html){\n            var _tag;\n            if (_reg.test(_html)){\n                _tag = _tmap[(RegExp.$1||'').toLowerCase()]||'';\n            }\n            var _div = _p._$create(_tag||'div');\n            _div.innerHTML = _html;\n            var _list = _p._$getChildren(_div);\n            return _list.length>1?_div:_list[0];\n        };\n    })();\n    /**\n     * 将dom节点转为xml串\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_p){\n     *       // 生成<div id=\"abc\">123</div>字符串\n     *       var _xml = _p._$dom2xml('abc'));\n     *   });\n     * ```\n     *\n     * @see    module:base/element._$xml2dom\n     * @method module:base/element._$dom2xml\n     * @param  {String|Node} arg0 - 节点\n     * @return {String}             XML代码\n     */\n    /**\n     * @method CHAINABLE._$dom2xml\n     * @see module:base/element._$dom2xml\n     */\n    _p._$dom2xml =\n    _y._$dom2xml = function(_element){\n        _element = _p._$get(_element);\n        return !_element?'':_h.__serializeDOM2XML(_element);\n    };\n    /**\n     * 将xml转为dom节点\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 生成<div id=\"abc\">123</div>节点\n     *       var _node = _e._$xml2dom('<div id=\"abc\">123</div>');\n     *   });\n     * ```\n     *\n     * @method module:base/element._$xml2dom\n     * @see    module:base/element._$dom2xml\n     * @param  {String} arg0 - xml文本\n     * @return {Node}          DOM节点\n     */\n    _p._$xml2dom = function(_xml){\n        _xml = (_xml||'').trim();\n        return !_xml?null:_h.__parseDOMFromXML(_xml);\n    };\n    /**\n     * dom节点转对象，多用于XML DOM转数据对象\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">123</div>\n     *\n     *   <div id=\"efg\">\n     *     <p>aaaa</p>\n     *     <span>bbbb</span>\n     *   </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_p){\n     *       // 返回对象{div:'123'}\n     *       var _obj = _p._$dom2object('abc');\n     *\n     *       // 返回对象{div:{p:'aaaa',span:'bbbb'}}\n     *       var _obj = _p._$dom2object('efg');\n     *   });\n     * ```\n     *\n     * @method module:base/element._$dom2object\n     * @see    module:base/element._$xml2object\n     * @param  {String|Node} arg0 - 节点\n     * @return {Object}             转换完成的对象\n     */\n    /**\n     * @method CHAINABLE._$dom2object\n     * @see module:base/element._$dom2object\n     */\n    _p._$dom2object =\n    _y._$dom2object = function(_dom,_obj){\n         _obj = _obj||{};\n         _dom = _p._$get(_dom);\n         if (!_dom) return _obj;\n        var _name = _dom.tagName.toLowerCase(),\n            _list = _p._$getChildren(_dom);\n        if (!_list||!_list.length){\n            _obj[_name] = _dom.textContent||_dom.text||'';\n            return _obj;\n        }\n        var _tmp = {};\n        _obj[_name] = _tmp;\n        _u._$forEach(\n            _list,function(_node){\n                _p._$dom2object(_node,_tmp);\n            }\n        );\n        return _obj;\n    };\n    /**\n     * XML转对象\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 返回 {user:{id:'1',username:'aaa',password:'123456'}}\n     *       var _obj = _e._$xml2object('\\\n     *           <?xml version=\"1.0\" encoding=\"utf-8\" ?>\\\n     *           <user>\\\n     *             <id>1</id>\\\n     *             <username>aaa</username>\\\n     *             <password>123456</password>\\\n     *           </user>\\\n     *       ');\n     *   });\n     * ```\n     *\n     * @method module:base/element._$xml2object\n     * @see    module:base/element._$dom2object\n     * @param  {String} arg0 - xml代码\n     * @return {Object}        对象\n     */\n    _p._$xml2object = function(_xml){\n        try{\n            return _p._$dom2object(_p._$xml2dom(_xml));\n        }catch(ex){\n            return null;\n        }\n    };\n    /**\n     * 文本转指定类型的数据\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 转成dom节点\n     *       var _dom = _e._$text2type('<div id=\"abc\">123</div>',\"xml\");\n     *       // 转成json字符串\n     *       var _json = _e._$text2type('{\"a\":\"aaaaaaaaaaaaa\"}',\"json\");\n     *       // 原样返回\n     *       var _text = _e._$text2type('<div id=\"abc\">123</div>');\n     *   });\n     * ```\n     *\n     * @method module:base/element._$text2type\n     * @param  {String} arg0 - 文本内容\n     * @param  {String} arg1 - 类型，如xml/json/text\n     * @return {Variable}      指定类型的数据\n     */\n    _p._$text2type = (function(){\n        var _fmap = {\n            xml:function(_text){\n                return _p._$xml2dom(_text);\n            },\n            json:function(_text){\n                try{\n                    return JSON.parse(_text);\n                }catch(ex){\n                    return null;\n                }\n            },\n            dft:function(_text){\n                return _text;\n            }\n        };\n        return function(_text,_type){\n            _type = (_type||'').toLowerCase();\n            return (_fmap[_type]||_fmap.dft)(_text||'');\n        };\n    })();\n    /**\n     * 批量设置节点样式\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       _e._$style('abc',{color:'red',width:'100px'});\n     *   });\n     * ```\n     *\n     * 输出结果\n     * ```html\n     *   <div id=\"abc\" style=\"color:red;width:100px;\">123</div>\n     * ```\n     *\n     * @method module:base/element._$style\n     * @see    module:base/element._$setStyle\n     * @param  {String|Node} arg0 - 节点\n     * @param  {Object}      arg1 - 样式信息{color:'red',width:'100px'}\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$style\n     * @see module:base/element._$style\n     */\n    _p._$style =\n    _y._$style = function(_element,_map){\n        _element = _p._$get(_element);\n        if (!!_element){\n            _u._$loop(_map,function(_value,_name){\n                _p._$setStyle(_element,_name,_value);\n            });\n        }\n    };\n    /**\n     * 设置单个样式\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       _e._$setStyle('abc','color','red');\n     *   });\n     * ```\n     *\n     * 输出结果\n     * ```html\n     *   <div id=\"abc\" style=\"color:red;\">123</div>\n     * ```\n     *\n     * @method module:base/element._$setStyle\n     * @see    module:base/element._$getStyle\n     * @param  {String|Node} arg0 - 节点\n     * @param  {String}      arg1 - 样式名称\n     * @param  {String}      arg2 - 样式值\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$setStyle\n     * @see module:base/element._$setStyle\n     */\n    _p._$setStyle =\n    _y._$setStyle = function(_element,_name,_value){\n        _element = _p._$get(_element);\n        if (!!_element){\n            _h.__setStyleValue(\n                _element,_name,\n                _h.__processCSSText(_value)\n            );\n        }\n    };\n    /**\n     * 取样式值\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\" style=\"color:red;\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 返回节点的颜色值red（高版本浏览器返回rgb值），如果没有返回空字符串\n     *       var _value = _e._$getStyle('abc','color');\n     *   });\n     * ```\n     *\n     * @method module:base/element._$getStyle\n     * @see    module:base/element._$setStyle\n     * @param  {String|Node} arg0 - 节点\n     * @param  {String}      arg1 - 样式名称\n     * @return {String}             样式值\n     */\n    /**\n     * @method CHAINABLE._$getStyle\n     * @see module:base/element._$getStyle\n     */\n    _p._$getStyle =\n    _y._$getStyle = function(_element,_name){\n        _element = _p._$get(_element);\n        return !_element ? '' :\n                _h.__getStyleValue(\n                    _element,_name\n                );\n    };\n    /**\n     * 页面注入脚本\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 注入脚本，全局执行环境\n     *       _e._$addScript('\\\n     *           document.getElementById(\"abc\").style.color = \"green\"\\\n     *       ');\n     *   });\n     * ```\n     *\n     * 输出结果\n     * ```html\n     *   <div id=\"abc\" style=\"color:green;\">123</div>\n     * ```\n     *\n     * @method module:base/element._$addScript\n     * @param  {String} arg0 - 脚本内容\n     * @return {Void}\n     */\n    _p._$addScript = function(_script){\n        try{\n            _script = _script.trim();\n            if (!!_script){\n                return (new Function(_script))();\n            }\n        }catch(ex){\n            // ignore\n            console.error(ex.message);\n            console.error(ex.stack);\n        }\n    };\n    /**\n     * 注入页面内联样式，\n     * 样式支持前缀标记$&lt;vendor&gt; ，\n     * 如下样式值支持3D/2D切换，优先选用3D，格式：$&lt;NAME|VALUE&gt;\n     *\n     * * NAME支持：scale/rotate/translate/matrix\n     * * VALUE格式：x=1&y=2&z=3&a=30\n     *\n     *\n     * 范例如$&lt;scale|a=30&gt;，各名称支持的参数列表\n     *\n     * | 名称              | 参数 |\n     * | :--        | :-- |\n     * | scale      | x,y,z |\n     * | rotate     | x,y,z,a |\n     * | translate  | x,y,z |\n     * | matrix     | m11,m12,m13,m14,m21,m22,m23,m24,m31,m32,m33,m34,m41,m42,m43,m44 |\n     *\n     *\n     * 结构举例\n     * ```html\n     *   <html>\n     *    <head>\n     *        <title>test</title>\n     *    </head>\n     *   </html>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 注入样式\n     *       _e._$addStyle('body{font-size:20px}');\n     *\n     *       // 注入样式支持变量\n     *       _e._$addStyle('\\\n     *           .a{$<vendor>transform-origin:0 0;}\\\n     *           .b{$<vendor>transform:$<translate|x=0&y=1&z=1>}\\\n     *       ');\n     *   });\n     * ```\n     *\n     * 输出结果\n     * ```html\n     *   <html>\n     *    <head>\n     *        <title>test</title>\n     *        <style>body{font-size:20px;}</style>\n     *        <style>\n     *           .a{-webkit-transform-origin:0 0;}\\\n     *           .b{-webkit-transform:translate3d(0,1,1);}\\\n     *        </style>\n     *    </head>\n     *   </html>\n     * ```\n     *\n     * @method module:base/element._$addStyle\n     * @param  {String} arg0 - 样式内容\n     * @return {Node}          样式节点\n     */\n    _p._$addStyle = (function(){\n        var _reg = /[\\s\\r\\n]+/gi;\n        return function(_css){\n            _css = (_css||'').replace(_reg,' ').trim();\n            var _node = null;\n            if (!!_css){\n                _node = _p._$create('style');\n                document.head.appendChild(_node);\n                _h.__injectCSSText(\n                    _node,_h.__processCSSText(_css)\n                );\n            }\n            return _node;\n        };\n    })();\n    /**\n     * 缓存待激活样式\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 设置样式到缓存中，自动生成样式名，返回自动生成的类名#<class>\n     *       var _class = _e._$pushCSSText('.#<uispace>{width:300px;}');\n     *\n     *       // 把缓存中的样式内联到页面\n     *       _e._$dumpCSSText();\n     *   });\n     * ```\n     *\n     * @method module:base/element._$pushCSSText\n     * @see    module:base/element._$dumpCSSText\n     * @param  {String} arg0 - 样式\n     * @return {String}        样式标识\n     */\n    _p._$pushCSSText = (function(){\n        var _reg = /#<(.*?)>/g,\n            _seed = +new Date;\n        return function(_css,_data){\n            if (!_cspol){\n                _cspol = [];\n            }\n            var _class = 'auto-'+_u._$uniqueID(),\n                _dmap = _u._$merge({uispace:_class},_data);\n            _cspol.push(\n                _css.replace(_reg,function($1,$2){\n                    return _dmap[$2]||$1;\n                })\n            );\n            return _class;\n        };\n    })();\n    /**\n     * 激活缓存中的样式\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\" class=\"item\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 设置样式.item{width:300px;}到缓存中\n     *       _e._$pushCSSText('.item{width:300px;}');\n     *\n     *       // 把缓存中的样式内联到页面\n     *       _e._$dumpCSSText();\n     *   });\n     * ```\n     *\n     * @method module:base/element._$dumpCSSText\n     * @see    module:base/element._$pushCSSText\n     * @return {Void}\n     */\n    _p._$dumpCSSText = function(){\n        if (!!_cspol){\n            _p._$addStyle(_cspol.join(' '));\n            _cspol = null;\n        }\n    };\n    /**\n     * 追加CSS规则\n     *\n     * 结构举例\n     * ```html\n     *   <style id=\"abc\"></style>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 设置样式.item{width:300px;}到缓存中\n     *       _e._$appendCSSText('node-id','.item{width:300px;}');\n     *   });\n     * ```\n     *\n     * @method module:base/element._$appendCSSText\n     * @see    module:base/element._$addStyle\n     * @param  {Node}   arg0 - 样式节点\n     * @param  {String} arg1 - 单条样式规则\n     * @return {CSSRule}       样式规则对象\n     */\n    /**\n     * @method CHAINABLE._$appendCSSText\n     * @see module:base/element._$appendCSSText\n     */\n    _p._$appendCSSText =\n    _y._$appendCSSText = function(_element,_css){\n        _element = _p._$get(_element);\n        return !_element ? null :\n                _h.__appendCSSText(\n                    _element,\n                    _h.__processCSSText(_css)\n                );\n    };\n    /**\n     * 新增样式类，多个样式用空格分开\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 添加样式 fc01 fc03\n     *       _e._$addClassName('abc','fc01 fc03');\n     *   });\n     * ```\n     *\n     * 输出结果\n     * ```html\n     *   <div id=\"abc\" class=\"fc01 fc03\">123</div>\n     * ```\n     *\n     * @method module:base/element._$addClassName\n     * @see    module:base/element._$delClassName\n     * @see    module:base/element._$replaceClassName\n     * @param  {String|Node} arg0 - 要操作的节点标识或者节点对象\n     * @param  {String}      arg1 - 要新增的样式类名称\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$addClassName\n     * @see module:base/element._$addClassName\n     */\n    _p._$addClassName =\n    _y._$addClassName = function(_element,_class){\n        if (!_class){\n            return;\n        }\n        _element = _p._$get(_element);\n        if (!!_element){\n            _h.__processClassName(\n                _element,'add',_class\n            );\n        }\n    };\n    /**\n     * 删除样式类，多个样式用空格分开\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\" class=\"fc01 fc03\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 删除fc02 fc03样式名\n     *       _e._$delClassName('abc','fc02 fc03');\n     *   });\n     * ```\n     *\n     * 输出结果\n     * ```html\n     *   <div id=\"abc\" class=\"fc01\">123</div>\n     * ```\n     *\n     * @method module:base/element._$delClassName\n     * @see    module:base/element._$addClassName\n     * @see    module:base/element._$replaceClassName\n     * @param  {String|Node} arg0 - 要操作的节点标识或者节点对象\n     * @param  {String}      arg1 - 要删除的样式类名称\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$delClassName\n     * @see module:base/element._$delClassName\n     */\n    _p._$delClassName =\n    _y._$delClassName = function(_element,_class){\n        _element = _p._$get(_element);\n        if (!!_element){\n            _h.__processClassName(\n                _element,'remove',_class\n            );\n        }\n    };\n    /**\n     * 替换节点的样式类名称，多个样式用空格分隔，\n     * 操作过程为先删除待删样式，再添加待添样式，因此不需要删除样式存在才添加样式\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\" class=\"fc01 fc03\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 替换fc02为fc05\n     *       // 这里不需要fc02存在\n     *       _e._$replaceClassName('abc','fc02','fc05');\n     *   });\n     * ```\n     *\n     * 输出结果\n     * ```html\n     *   <div id=\"abc\" class=\"fc01 fc03 fc05\">123</div>\n     * ```\n     *\n     * @method module:base/element._$replaceClassName\n     * @see    module:base/element._$addClassName\n     * @see    module:base/element._$delClassName\n     * @param  {String|Node} arg0 - 要操作的节点标识或者节点对象\n     * @param  {String}      arg1 - 要删除的样式类名称\n     * @param  {String}      arg2 - 要新增的样式类名称\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$replaceClassName\n     * @see module:base/element._$replaceClassName\n     */\n    _p._$replaceClassName =\n    _y._$replaceClassName = function(_element,_del,_add){\n        _element = _p._$get(_element);\n        if (!!_element){\n            _h.__processClassName(\n                _element,'replace',\n                _del,_add\n            );\n        }\n    };\n    /**\n     * 检测节点是否包含指定样式，多个样式用空格分隔，检测时包含其中之一即表示包含\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\" class=\"fc01 fc03\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 如果有fc01样式返回true，否则返回false\n     *       _e._$hasClassName('abc',\"fc01\");\n     *   });\n     * ```\n     *\n     * @method module:base/element._$hasClassName\n     * @param  {String|Node} arg0 - 节点标识或者对象\n     * @param  {String}      arg1 - 样式串\n     * @return {Boolean}            是否含指定样式\n     */\n    /**\n     * @method CHAINABLE._$hasClassName\n     * @see module:base/element._$hasClassName\n     */\n    _p._$hasClassName =\n    _y._$hasClassName = function(_element,_class){\n        _element = _p._$get(_element);\n        if (!!_element){\n            return _h.__hasClassName(_element,_class);\n        }\n        return !1;\n    };\n    /**\n     * 取样式变换矩阵对象\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 生成下面矩阵的对象\n     *       // |a:1,b:0,c:0,d:1,e:0:f:0|\n     *       // |m11:1,m12:0,m13:0,m14:0|\n     *       // |m21:0,m22:1,m23:0,m24:0|\n     *       // |m31:0,m32:0,m33:1,m34:0|\n     *       // |m41:0,m42:0,m43:0,m44:1|\n     *       var _matrix = _e._$matrix(\"matrix(1,0,0,1,0,0)\");\n     *   });\n     * ```\n     *\n     * @method module:base/element._$matrix\n     * @param  {String} arg0 - 变化信息\n     * @return {CSSMatrix}     变换矩阵对象\n     */\n    _p._$matrix = function(_matrix){\n        _matrix = (_matrix||'').trim();\n        return _h.__getCSSMatrix(_matrix);\n    };\n    /**\n     * 设置3D变换，对于不支持3D的系统自动切换为2D变换\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\"></div>\n     * ```\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/element'\n     *   ],function(_e){\n     *       // 进行css3d变换，对应css样式为-webkit-transform:rotate3d( 2, 1, 1, -75deg);\n     *       _e._$css3d('abc','rotate',{x:2,y:1,z:1,a:'-75deg'});\n     *   });\n     * ```\n     *\n     * @method module:base/element._$css3d\n     * @see    module:base/element._$addStyle\n     * @param  {String|Node} arg0 - 节点标识或者对象\n     * @param  {String}      arg1 - 变换类型，matrix/translate/scale/rotate\n     * @param  {Object}      arg2 - 变换值，{x:1,y:2,z:3,a:'30deg'}\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$css3d\n     * @see module:base/element._$css3d\n     */\n    _p._$css3d =\n    _y._$css3d = function(_element,_name,_map){\n        _element = _p._$get(_element);\n        if (!!_element){\n            var _value = _h.__processTransformValue(_name,_map);\n            if (!!_value){\n                _p._$setStyle(_element,'transform',_value);\n            }\n        }\n    };\n    // for chainable\n    _x._$merge(_y);\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.e'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/base/event.js",
    "content": "/*\n * ------------------------------------------\n * 事件接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module base/event */\nNEJ.define([\n    './global.js',\n    './element.js',\n    './util.js',\n    './chain.js',\n    '{platform}event.js'\n],function(NEJ,_e,_u,_x,_h,_p,_o,_f,_r){\n    // {id:{type:[{type:'click',func:function,sfun:function,capt:true},...]}}\n    // id   - element id\n    // type - event name, no on prefix\n    // func - event after wrapper\n    // capt - capture flag\n    // sfun - event before wrapper\n    // link - events link to this event [[element,type,handler,capture],...]\n    var _xcache = {},\n        _y = {}; // chainable methods\n    /*\n     * 取事件类型列表\n     * @param  {String} 事件类型\n     * @return {Array}  事件列表\n     */\n    var _getTypeList = (function(){\n        var _reg = /[\\s,;]+/;\n        return function(_type){\n            var _type = (_type||'').trim().toLowerCase();\n            return !_type?null:_type.split(_reg);\n        };\n    })();\n    /*\n     * 取鼠标相对于BODY的偏移\n     * @param  {Event}  事件对象\n     * @param  {String} 类型，X/Y\n     * @param  {String} 滚动偏移名称，Left/Top\n     * @return {Void}\n     */\n    var _getClientOffset = function(_event,_type,_name){\n        var _key1 = 'page'+_type;\n        return _event[_key1]!=null?_event[_key1]:(\n            _event['client'+_type]+\n            _e._$getPageBox()['scroll'+_name]\n        );\n    };\n    /*\n     * 取鼠标相对于页面的偏移\n     * @param  {Event}  事件对象\n     * @param  {String} 类型，X/Y\n     * @param  {String} 滚动偏移名称，Left/Top\n     * @return {Void}\n     */\n    var _getPageOffset = function(_event,_type,_name){\n        var _key3 = 'scroll'+_name;\n            _node = _p._$getElement(_event),\n            _xret = _getClientOffset(_event,_type,_name);\n        while(!!_node&&\n                _node!=document.body&&\n                _node!=document.documentElement){\n            _xret += _node[_key3]||0;\n            _node = _node.parentNode;\n        }\n        return _xret;\n    };\n    /*\n     * 格式化添加删除事件接口参数\n     * @param  {String|Node} 节点ID或者对象\n     * @param  {String}      事件类型，不带on前缀，不区分大小写，多个事件用空格分隔\n     * @param  {Function}    事件处理函数\n     * @param  {Boolean}     是否捕获阶段事件，IE低版本浏览器忽略此参数\n     * return  {Object}      格式化后参数\n     */\n    var _doFormatArgs = function(_element,_type,_handler,_capture){\n        var _result = {};\n        // check element\n        _element = _e._$get(_element);\n        if (!_element){\n            return null;\n        }\n        _e._$id(_element);\n        _result.element = _element;\n        // check event handler\n        if (!_u._$isFunction(_handler)){\n            return null;\n        }\n        _result.handler = _handler;\n        // check type\n        var _type = _getTypeList(_type);\n        if (!_type){\n            return null;\n        }\n        // save info\n        _result.type = _type;\n        _result.capture = !!_capture;\n        return _result;\n    };\n    /**\n     * 节点添加事件，\n     * 支持添加自定义事件，\n     * 对于自定义事件的实现逻辑由其他模块负责实现\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/event'\n     *   ],function(_v){\n     *       // 添加系统预定义事件\n     *       _v._$addEvent(\n     *           'abc','mouseover',function(_event){\n     *               // TODO something\n     *           },false\n     *       );\n     *\n     *       // 添加自定义事件，回车事件\n     *       _v._$addEvent(\n     *           'abc','enter',function(_event){\n     *               // TODO something\n     *           },false\n     *       );\n     *\n     *       // 添加多个事件，用空格分隔\n     *       _v._$addEvent(\n     *           'abc','mouseover click mousedown',\n     *           function(_event){\n     *               // TODO something\n     *           },false\n     *       );\n     *   });\n     * ```\n     *\n     * 带自定义事件的类构造或者对象\n     * ```javascript\n     * NEJ.define([\n     *     'base/klass',\n     *     'base/event',\n     *     'util/event',\n     *     'util/event/event'\n     * ],function(_k,_v,_t0,_t1,_p){\n     *     // 定义类\n     *     _p._$$Klass = _k._$klass();\n     *     var _pro = _p._$$Klass._$extend(_t0._$$EventTarget);\n     *     \n     *     // TODO\n     *     \n     *     // 添加自定义事件支持\n     *     // 对节点的事件同样支持此自定义事件\n     *     _t1._$$CustomEvent._$allocate({\n     *         element:_p._$$Klass,\n     *         event:['ok','fail']\n     *     });\n     * \n     *     // 使用事件接口添加/删除/调度事件\n     *     var _handler = function(_event){\n     *         // TODO\n     *     };\n     *     _v._$addEvent(_p._$$Klass,'ok',_handler);\n     *     _v._$delEvent(_p._$$Klass,'ok',_handler);\n     * });\n     * ```\n     * \n     * @method module:base/event._$addEvent\n     * @see    module:base/event._$delEvent\n     * @param  {String|Node|Object} arg0 - 节点或者类构造或者对象\n     * @param  {String}      arg1 - 事件类型，不带on前缀，不区分大小写，多个事件用空格分隔\n     * @param  {Function}    arg2 - 事件处理函数\n     * @param  {Boolean}     arg3 - 是否捕获阶段事件，IE低版本浏览器忽略此参数\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$addEvent\n     * @see module:base/event._$addEvent\n     */\n    _p._$addEvent = \n    _y._$addEvent = (function(){\n        // cache event\n        // type/handler/link\n        var _doCacheEvent = function(_type,_source,_real){\n            var _id = _e._$id(_source.element),\n                _cch_id = _xcache[_id]||{},\n                _cch_tp = _cch_id[_type]||[];\n            _cch_tp.push({\n                type:_real.type||_type,\n                func:_real.handler||_source.handler,\n                sfun:_source.handler,\n                capt:_source.capture,\n                link:_real.link,\n                destroy:_real.destroy\n            });\n            _cch_id[_type] = _cch_tp;\n            _xcache[_id] = _cch_id;\n        };\n        return function(){\n            var _args = _doFormatArgs.apply(null,arguments);\n            if (!_args) return;\n            _u._$forEach(\n                _args.type,function(_name){\n                    var _argc = _h.__checkEvent(\n                        _args.element,\n                        _name,_args.handler\n                    );\n                    // add event\n                    _h.__addEvent(\n                        _args.element,_argc.type,\n                        _argc.handler,_args.capture\n                    );\n                    // add event link\n                    _u._$forIn(\n                        _argc.link,function(_item){\n                            _item[3] = !!_item[3];\n                            _h.__addEvent.apply(_h,_item);\n                            _item[0] = _e._$id(_item[0]);\n                        }\n                    );\n                    // cache event\n                    _doCacheEvent(_name,_args,_argc);\n                }\n            );\n        };\n    })();\n    /**\n     * 节点删除事件，输入参数必须保证与添加接口_$addEvent输入参数完全一致\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/event'\n     *   ],function(_v){\n     *       // 事件回调业务逻辑\n     *       var _doCallback = function(_event){\n     *           // TODO something\n     *           alert('0');\n     *       };\n     *\n     *       // 添加事件\n     *       _v._$addEvent('abc','mouseover',_doCallback,false);\n     *       // 删除事件，这里参数必须保持完全一致\n     *       _v._$delEvent('abc','mouseover',_doCallback,false);\n     *\n     *       // 比如以下方式虽然回调的业务逻辑一致，但是无法删除之前添加的事件\n     *       _v._$delEvent(\n     *           'abc',\"mouseover\",function(_event){\n     *               // TODO something\n     *               alert('0');\n     *           },false\n     *       );\n     *\n     *       // 删除多个事件\n     *       _v._$delEvent(\n     *           'abc','mouseover click mouseup',\n     *           _doCallback,false\n     *       );\n     *   });\n     * ```\n     *\n     * @method module:base/event._$delEvent\n     * @see    module:base/event._$addEvent\n     * @param  {String|Node} arg0 - 节点ID或者对象\n     * @param  {String}      arg1 - 事件类型，不带on前缀，不区分大小写，多个事件用空格分隔\n     * @param  {Function}    arg2 - 事件处理函数\n     * @param  {Boolean}     arg3 - 是否捕获阶段事件\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$delEvent\n     * @see module:base/event._$delEvent\n     */\n    _p._$delEvent = \n    _y._$delEvent = (function(){\n        var _unCacheEvent = function(_type,_conf){\n            var _id = _e._$id(_conf.element),\n                _cch_id = _xcache[_id]||_o,\n                _cch_tp = _cch_id[_type],\n                _index = _u._$indexOf(\n                    _cch_tp,function(_item){\n                        // check handler and capture\n                        return _item.sfun===_conf.handler&&\n                               _item.capt===_conf.capture;\n                    }\n                );\n            // check result\n            var _result = null;\n            if (_index>=0){\n                var _item = _cch_tp.splice(_index,1)[0];\n                _result = [[\n                    _conf.element,_item.type,\n                    _item.func,_conf.capture\n                ]];\n                if (!!_item.link){\n                    // complete element by id\n                    _u._$forEach(_item.link,function(v){\n                        v[0] = _e._$get(v[0]);\n                    });\n                    _result.push.apply(_result,_item.link);\n                }\n                if (!!_item.destroy){\n                    _item.destroy();\n                }\n                // clear cache\n                if (!_cch_tp.length){\n                    delete _cch_id[_type];\n                }\n                if (!_u._$hasProperty(_cch_id)){\n                    delete _xcache[_id];\n                }\n            }\n            return _result;\n        };\n        return function(){\n            var _args = _doFormatArgs.apply(null,arguments);\n            if (!_args) return;\n            _u._$forEach(\n                _args.type,function(_name){\n                    _u._$forEach(\n                        _unCacheEvent(_name,_args),\n                        function(_item){\n                            _h.__delEvent.apply(_h,_item);\n                        }\n                    );\n                }\n            );\n        };\n    })();\n    /**\n     * 清除节点事件\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/event'\n     *   ],function(_v){\n     *       // 添加事件\n     *       _v._$addEvent(\n     *           'abc','mouseover',function(_event){\n     *               // TODO something\n     *           }\n     *       );\n     *       _v._$addEvent(\n     *           'abc','mouseover',function(_event){\n     *               // TODO something\n     *           },true\n     *       );\n     *       _v._$addEvent(\n     *           'abc','custom',function(_event){\n     *               // TODO something\n     *           }\n     *       );\n     *\n     *       // 清除节点所有事件，包括两个mouseover事件和一个custom事件\n     *       _v._$clearEvent('abc');\n     *\n     *       // 清除节点指定类型事件，只清除两个mouseover事件\n     *       _v._$clearEvent('abc','mouseover');\n     *\n     *       // 清除多个事件，用空格分隔\n     *       _v._$clearEvent('abc','mouseover custom');\n     *   });\n     * ```\n     *\n     * @method module:base/event._$clearEvent\n     * @see    module:base/event._$delEvent\n     * @param  {String|Node} arg0 - 节点ID或者对象\n     * @param  {String}      arg1 - 事件类型，不带on前缀，不区分大小写，多个事件用空格分隔\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$clearEvent\n     * @see module:base/event._$clearEvent\n     */\n    _p._$clearEvent = \n    _y._$clearEvent = (function(){\n        var _doClearEvent = function(_id,_name,_list){\n            _u._$reverseEach(\n                _list,function(_item){\n                    _p._$delEvent(\n                        _id,_name,_item.sfun,_item.capt\n                    );\n                }\n            );\n        };\n        return function(_element,_type){\n            var _id = _e._$id(_element);\n            if (!_id) return;\n            var _cch_id = _xcache[_id];\n            if (!!_cch_id){\n                _type = _getTypeList(_type);\n                if (!!_type){\n                    // clear event by type\n                    _u._$forEach(\n                        _type,function(_name){\n                            _doClearEvent(_id,_name,_cch_id[_name]);\n                        }\n                    );\n                }else{\n                    // clear all event\n                    _u._$loop(\n                        _cch_id,function(_value,_name){\n                            _p._$clearEvent(_element,_name);\n                        }\n                    );\n                }\n            }\n        };\n    })();\n    /**\n     * 触发对象的某个事件，注：对于IE浏览器该接口节点事件有以下限制\n     *\n     * * 捕获阶段支持需要浏览器IE9+\n     * * 节点上自定义事件支持需要浏览器IE9+\n     *\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/event'\n     *   ],function(_v){\n     *       // 注册鼠标事件\n     *       _v._$addEvent(\n     *           'abc','click',function(_event){\n     *               // 获取鼠标事件触发的垂直位置\n     *               var _y = _v._$pageY(_event);\n     *           }\n     *       );\n     *       // 触发鼠标事件\n     *       _v._$dispatchEvent('abc','click');\n     *\n     *       // 注册自定义事件\n     *       _v._$addEvent(\n     *           'abc','ok',function(_event){\n     *               // TODO something\n     *           }\n     *       );\n     *       // 触发自定义事件\n     *       _v._$dispatchEvent('abc','ok');\n     *   });\n     * ```\n     *\n     * @method module:base/event._$dispatchEvent\n     * @param  {String|Node} arg0 - 节点ID或者对象\n     * @param  {String}      arg1 - 鼠标事件类型，不区分大小写，多个事件用空格分隔\n     * @param  {Object}      arg2 - 传递的参数信息\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$dispatchEvent\n     * @see module:base/event._$dispatchEvent\n     */\n    _p._$dispatchEvent = \n    _y._$dispatchEvent = function(_element,_type,_options){\n        var _element = _e._$get(_element);\n        if (!!_element){\n            _u._$forEach(\n                _getTypeList(_type),function(_name){\n                    var _result = _h.__checkEvent(\n                        _element,_name\n                    );\n                    _h.__dispatchEvent(\n                        _element,_result.type,_options\n                    );\n                }\n            );\n        }\n    };\n    /**\n     * 获取触发事件的节点，可以传入过滤接口来遍历父节点找到符合条件的节点\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"a\">\n     *     <p>\n     *       <span id=\"b\">123</span>\n     *       <span link=\"a\">123</span>\n     *       <span class=\"a link\">123</span>\n     *       <span data-link=\"a\">123</span>\n     *       <label>aaaaa</label>\n     *     </p>\n     *   </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/event'\n     *   ],function(_v){\n     *       // 取事件触发节点\n     *       _v._$addEvent(\n     *           'b','click',function(_event){\n     *               // id为b的节点\n     *               var _node = _v._$getElement(_event);\n     *               // TODO something\n     *           }\n     *       );\n     *\n     *       // 事件触发，取id是a的节点\n     *       _v._$addEvent(\n     *           'b','click',function(_event){\n     *               // id为a的节点\n     *               var _node = _v._$getElement(\n     *                   _event,function(_element){\n     *                       return _element.id=='a';\n     *                   }\n     *               );\n     *               // TODO something\n     *\n     *               // class含link或者属性含link或者data-link的节点\n     *               var _node = _v._$getElement(_event,'link');\n     *\n     *               // 仅匹配class即 class=\"link xx xxx\"\n     *               var _node = _v._$getElement(_event,'c:link');\n     *\n     *               // 仅匹配dataset即 data-link=\"aaaa\"\n     *               var _node = _v._$getElement(_event,'d:link');\n     *\n     *               // 仅匹配attributer即 link=\"aaa\"\n     *               var _node = _v._$getElement(_event,'a:link');\n     *\n     *               // 仅匹配tag即 <label>\n     *               var _node = _v._$getElement(_event,'t:label');\n     *           }\n     *       );\n     *   });\n     * ```\n     *\n     * @method module:base/event._$getElement\n     * @param  {Event}    arg0 - 事件对象\n     * @param  {Function} arg1 - 过滤接口\n     * @return {Node}            符合条件的节点\n     */\n    _p._$getElement = function(_event){\n        if (!_event) return null;\n        var _element = _event.target||\n                _event.srcElement,\n            _filter = arguments[1];\n        return _e._$getParent(_element,_filter);\n    };\n    /**\n     * 阻止事件，包括默认事件和传递事件\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"a\">\n     *     <a href=\"xxx.html\" id=\"b\">123</a>\n     *   </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/event'\n     *   ],function(_v){\n     *       // 事件回调中阻止事件冒泡\n     *       _v._$addEvent(\n     *           'b','click',function(_event){\n     *               // 阻止事件继续传播\n     *               // 阻止链接打开的默认事件\n     *               _v._$stop(_event);\n     *           }\n     *       );\n     *\n     *       // a节点上的点击事件不会触发\n     *       _v._$addEvent(\n     *           'a','click',function(_event){\n     *               alert(0);\n     *               // TODO something\n     *           }\n     *       );\n     *   });\n     * ```\n     *\n     * @method module:base/event._$stop\n     * @see    module:base/event._$stopBubble\n     * @see    module:base/event._$stopDefault\n     * @param  {Event} arg0 - 要阻止的事件对象\n     * @return {Void}\n     */\n    _p._$stop = function(_event){\n        _p._$stopBubble(_event);\n        _p._$stopDefault(_event);\n    };\n    /**\n     * 阻止事件的冒泡传递\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"a\">\n     *     <a href=\"xxx.html\" id=\"b\">123</a>\n     *   </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/event'\n     *   ],function(_v){\n     *       // 事件回调中阻止事件冒泡\n     *       _v._$addEvent(\n     *           'b','click',function(_event){\n     *               // 阻止事件继续传播\n     *               // 链接仍然会被打开\n     *               _v._$stopBubble(_event);\n     *           }\n     *       );\n     *\n     *       // a节点上的点击事件不会触发\n     *       _v._$addEvent(\n     *           'a','click',function(_event){\n     *               alert(0);\n     *               // TODO something\n     *           }\n     *       );\n     *   });\n     * ```\n     *\n     * @see    module:base/event._$stop}\n     * @method module:base/event._$stopBubble\n     * @param  {Event} arg0 - 要阻止的事件对象\n     * @return {Void}\n     */\n    _p._$stopBubble = function(_event){\n        if (!!_event){\n            !!_event.stopPropagation\n            ? _event.stopPropagation()\n            : _event.cancelBubble = !0;\n        }\n    };\n    /**\n     * 阻止标签的默认事件\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"a\">\n     *     <a href=\"xxx.html\" id=\"b\">123</a>\n     *   </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/event'\n     *   ],function(_v){\n     *       // 事件回调中阻止链接默认事件\n     *       _v._$addEvent(\n     *           'b','click',function(_event){\n     *               // 阻止链接打开页面的默认行为\n     *               _v._$stopDefault(_event);\n     *           }\n     *       );\n     *\n     *       // a节点上的点击事件仍然会触发\n     *       _v._$addEvent(\n     *           'a','click',function(_event){\n     *               alert(0);\n     *               // TODO something\n     *           }\n     *       );\n     *   });\n     * ```\n     *\n     * @method module:base/event._$stopDefault\n     * @see    module:base/event._$stop\n     * @param  {Event} arg0 - 要阻止的事件对象\n     * @return {Void}\n     */\n    _p._$stopDefault = function(_event) {\n        if (!!_event){\n            !!_event.preventDefault\n            ? _event.preventDefault()\n            : _event.returnValue = !1;\n        }\n    };\n    /**\n     * 取事件相对于页面的位置\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\" style=\"width:100%;height:100%;\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/event'\n     *   ],function(_v){\n     *       // 回调中取鼠标位置\n     *       _v._$addEvent(\n     *           'abc','click',function(_event){\n     *               // 获取鼠标事件触发的水平、垂直位置\n     *               var _pos = _v._$page(_event);\n     *           }\n     *       );\n     *   });\n     * ```\n     *\n     * @method module:base/event._$page\n     * @see    module:base/event._$pageX\n     * @see    module:base/event._$pageY\n     * @param  {Event}  arg0 - 事件对象\n     * @return {Object}        位置信息，{x:10,y:10}\n     */\n    _p._$page = function(_event){\n        return {\n            x:_p._$pageX(_event),\n            y:_p._$pageY(_event)\n        };\n    };\n    /**\n     * 取事件相对于页面左侧的位置，累加所有内部滚动高度\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\" style=\"width:100%;height:100%;\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/event'\n     *   ],function(_v){\n     *       // 回调中取鼠标位置\n     *       _p._$addEvent(\n     *           'abc','click',function(_event){\n     *               // 获取鼠标事件触发的水平位置\n     *               var _x = _v._$pageX(_event);\n     *           }\n     *       );\n     *   });\n     * ```\n     *\n     * @method module:base/event._$pageX\n     * @see    module:base/event._$clientX\n     * @param  {Event}  arg0 - 事件对象\n     * @return {Number}        水平位置\n     */\n    _p._$pageX = function(_event){\n        return _getPageOffset(_event,'X','Left');\n    };\n    /**\n     * 取事件相对于页面顶部的位置，累加所有内部滚动高度\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\" style=\"width:100%;height:100%;\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/event'\n     *   ],function(_v){\n     *       // 回调中取鼠标位置\n     *       _v._$addEvent(\n     *           'abc','click',function(_event){\n     *               // 获取鼠标事件触发的垂直位置\n     *               var _y = _v._$pageY(_event);\n     *           }\n     *       );\n     *   });\n     * ```\n     *\n     * @method module:base/event._$pageY\n     * @see    module:base/event._$clientY\n     * @param  {Event}  arg0 - 事件对象\n     * @return {Number}        垂直位置\n     */\n    _p._$pageY = function(_event){\n        return _getPageOffset(_event,'Y','Top');\n    };\n    /**\n     * 取事件相对于页面左侧的位置，仅累加页面滚动高度\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\" style=\"width:100%;height:100%;\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/event'\n     *   ],function(_v){\n     *       // 回调中取鼠标位置\n     *       _p._$addEvent(\n     *           'abc','click',function(_event){\n     *               // 获取鼠标事件触发的水平位置\n     *               var _x = _v._$clientX(_event);\n     *           }\n     *       );\n     *   });\n     * ```\n     *\n     * @method module:base/event._$clientX\n     * @see    module:base/event._$pageX\n     * @param  {Event}  arg0 - 事件对象\n     * @return {Number}        水平位置\n     */\n    _p._$clientX = function(_event){\n        return _getClientOffset(_event,'X','Left');\n    };\n    /**\n     * 取事件相对于页面顶部的位置，仅累加页面滚动高度\n     *\n     * 结构举例\n     * ```html\n     *   <div id=\"abc\" style=\"width:100%;height:100%;\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/event'\n     *   ],function(_v){\n     *       // 回调中取鼠标位置\n     *       _v._$addEvent(\n     *           'abc','click',function(_event){\n     *               // 获取鼠标事件触发的垂直位置\n     *               var _y = _v._$pageY(_event);\n     *           }\n     *       );\n     *   });\n     * ```\n     *\n     * @method module:base/event._$clientY\n     * @see    module:base/event._$pageY\n     * @param  {Event}  arg0 - 事件对象\n     * @return {Number}        垂直位置\n     */\n    _p._$clientY = function(_event){\n        return _getClientOffset(_event,'Y','Top');\n    };\n    \n    // for chainable method\n    _x._$merge(_y);\n    \n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.v'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/base/global.js",
    "content": "/*\n * --------------------------------------------\n * 原生对象扩展接口\n * @version 1.0\n * @author  genify(caijf@corp.netease.com)\n * --------------------------------------------\n */\n/**\n * 全局window对象\n * @external window\n */\n/**\n * 全局页面文档对象\n * @external document\n */\n/**\n * 全局location对象\n * @external location\n */\n/**\n * 全局history对象\n * @external history\n */\n/**\n * 内置函数对象扩展\n * @external Function\n */\nNEJ.define(function(_p,_o,_f,_r){\n    var _extpro = Function.prototype;\n    /**\n     * AOP增强操作，增强操作接受一个输入参数包含以下信息\n     *\n     *  | 参数名称 | 参数类型  | 参数描述 |\n     *  | :--     | :--      | :-- |\n     *  | args    | Array    | 函数调用时实际输入参数，各增强操作中可以改变值后将影响至后续的操作 |\n     *  | value   | Variable | 输出结果 |\n     *  | stopped | Boolean  | 是否结束操作，终止后续操作 |\n     *\n     * @method external:Function#_$aop\n     * @param  {Function} arg0 - 前置操作，接受一个输入参数，见描述信息\n     * @param  {Function} arg1 - 后置操作，接受一个输入参数，见描述信息\n     * @return {Function}        增强后操作函数\n     */\n    _extpro._$aop = function(_before,_after){\n        var _after = _after||_f,\n            _before = _before||_f,\n            _handler = this;\n        return function(){\n            var _event = {args:_r.slice.call(arguments,0)};\n            _before(_event);\n            if (!_event.stopped){\n                _event.value = _handler.apply(this,_event.args);\n                _after(_event);\n            }\n            return _event.value;\n        };\n    };\n    /**\n     * 绑定接口及参数，使其的调用对象保持一致\n     *\n     *  ```javascript\n     *  var scope = {a:0};\n     * \n     *  var func = function(a,b){\n     *      // 第一个参数 ：1\n     *      console.log(a);\n     *      // 第二个参数 ： 2\n     *      consoel.log(b);\n     *      // 当前this.a ： 0\n     *      console.log(this.a);\n     *  };\n     * \n     *  func._$bind(scope,\"1\")(2);\n     *  ```\n     *\n     * @method external:Function#_$bind\n     * @see    external:Function#_$bind2\n     * @param  {Object} arg0 - 需要保持一致的对象，null表示window对象，此参数外的其他参数作为绑定参数\n     * @return {Function}      返回绑定后的函数\n     */\n    _extpro._$bind = function() {\n        var _args = arguments,\n            _object = arguments[0],\n            _function = this;\n        return function(){\n            // not use slice for chrome 10 beta and Array.apply for android\n            var _argc = _r.slice.call(_args,1);\n            _r.push.apply(_argc,arguments);\n            return _function.apply(_object||null,_argc);\n        };\n    };\n    /**\n     * 绑定接口及参数，使其的调用对象保持一致，\n     * 该接口与_$bind接口的差别在于绑定时参数和调用时参数的顺序不一样，\n     * _$bind优先传入绑定时参数，_$bind2优先传入调用时参数\n     *\n     *  ```javascript\n     *  var scope = {a:0};\n     * \n     *  var func = function(a,b){\n     *      // 第一个参数 ：2\n     *      console.log(a);\n     *      // 第二个参数 ： 1\n     *      consoel.log(b);\n     *      // 当前this.a ： 0\n     *      console.log(this.a);\n     *  };\n     * \n     *  func._$bind(scope,\"1\")(2);\n     *  ```\n     *\n     * @method external:Function#_$bind2\n     * @see    external:Function#_$bind\n     * @param  {Object} arg0 - 需要保持一致的对象，null表示window对象，此参数外的其他参数作为绑定参数\n     * @return {Function}      返回绑定后的事件函数\n     */\n    _extpro._$bind2 = function() {\n        var _args = arguments,\n            _object = _r.shift.call(_args),\n            _function = this;\n        return function(){\n            _r.push.apply(arguments,_args);\n            return _function.apply(_object||null,arguments);\n        };\n    };\n    // for compatiable\n    var _extpro = String.prototype;\n    if (!_extpro.trim){\n         _extpro.trim = (function(){\n            var _reg = /(?:^\\s+)|(?:\\s+$)/g;\n            return function(){\n                return this.replace(_reg,'');\n            };\n         })();\n    }\n    if (!this.console){\n        this.console = {\n            log:_f,\n            error:_f\n        };\n    }\n\n    if (CMPT){\n        NEJ = this.NEJ||{};\n        // copy object properties\n        // only for nej compatiable\n        NEJ.copy = function(a,b){\n            a = a||{};\n            b = b||_o;\n            for(var x in b){\n                if (b.hasOwnProperty(x)){\n                    a[x] = b[x];\n                }\n            }\n            return a;\n        };\n        // NEJ namespace\n        NEJ = NEJ.copy(\n            NEJ,{\n                O:_o,R:_r,F:_f,\n                P:function(_namespace){\n                    if (!_namespace||!_namespace.length){\n                        return null;\n                    }\n                    var _package = window;\n                    for(var a=_namespace.split('.'),\n                            l=a.length,i=(a[0]=='window')?1:0;i<l;\n                            _package=_package[a[i]]=_package[a[i]]||{},i++);\n                    return  _package;\n                }\n            }\n        );\n        \n        return NEJ;\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/base/klass.js",
    "content": "/*\n * --------------------------------------------\n * NEJ类模型\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * --------------------------------------------\n */\n/** @module base/klass */\nNEJ.define([\n    './global.js',\n    '{platform}util.js'\n],function(NEJ,_u,_p,_o,_f,_r){\n    /**\n     * 定义类，通过此api定义的类具有以下特性：\n     *\n     * * {@link external:Function#_$extend|_$extend}作为类的静态扩展方法\n     * * __init作为类的初始化函数\n     * * __super作为子类调用父类的同名函数\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/klass'\n     * ],function(k,p){\n     *     // 定义类A\n     *     p.A = k._$klass();\n     *     var pro = A.prototype;\n     *     // 初始化\n     *     pro.__init = function(){\n     *          // do init\n     *     };\n     *     // 类接口\n     *     pro.__doSomething = function(a){\n     *         // TODO something\n     *     };\n     * \n     *     return p;\n     * });\n     * ```\n     * \n     * ```javascript\n     * NEJ.define([\n     *     'base/klass',\n     *     '/path/to/class/a.js'\n     * ],function(k,a,p){\n     *     // 定义类B，并继承自A\n     *     p.B = k._$klass();\n     *     var pro = B._$extend(a.A);\n     *     // 初始化\n     *     pro.__init = function(){\n     *         // 调用A的初始化逻辑\n     *         this.__super();\n     *         // TODO B的初始化逻辑\n     *     };\n     *     // 类接口\n     *     pro.__doSomething = function(a){\n     *         // 调用A的__doSomething接口\n     *         this.__super(a);\n     *         // TODO B的逻辑\n     *     };\n     * \n     *     return p;\n     * });\n     * ```\n     * \n     * @method module:base/klass._$klass\n     * @see    external:Function#_$extend\n     * @return {Function} 返回定义的类\n     */\n    _p._$klass = (function(){\n        var _isNotFunction = function(){\n            return _o.toString.call(arguments[0])!=='[object Function]';\n        };\n        var _doFindIn = function(_method,_klass){\n            while(!!_klass){\n                var _pro = _klass.prototype,\n                    _key = _u.__forIn(_pro,function(v){\n                        return _method===v;\n                    });\n                if (_key!=null){\n                    return {\n                        name:_key,\n                        klass:_klass\n                    };\n                }\n                _klass = _klass._$super;\n            }\n        };\n        return function(){\n            // class constructor\n            var _Klass = function(){\n                return this.__init.apply(this,arguments);\n            };\n            _Klass.prototype.__init = _f;\n            /**\n             * 子类继承父类\n             *\n             * ```javascript\n             * NEJ.define([\n             *     'base/klass'\n             * ],function(k,p){\n             *     // 定义类A\n             *     p.A = k._$klass();\n             *     var pro = A.prototype;\n             *     // 初始化\n             *     pro.__init = function(){\n             *          // do init\n             *     };\n             *     // 类接口\n             *     pro.__doSomething = function(a){\n             *         // TODO something\n             *     };\n             * \n             *     return p;\n             * });\n             * ```\n             * \n             * ```javascript\n             * NEJ.define([\n             *     'base/klass',\n             *     '/path/to/class/a.js'\n             * ],function(k,a,p){\n             *     // 定义类B，并继承自A\n             *     p.B = k._$klass();\n             *     var pro = B._$extend(a.A);\n             *     // 初始化\n             *     pro.__init = function(){\n             *         // 调用A的初始化逻辑\n             *         this.__super();\n             *         // TODO B的初始化逻辑\n             *     };\n             *     // 类接口\n             *     pro.__doSomething = function(a){\n             *         // 调用A的__doSomething接口\n             *         this.__super(a);\n             *         // TODO B的逻辑\n             *     };\n             * \n             *     return p;\n             * });\n             * ```\n             *\n             * @method external:Function#_$extend\n             * @see    module:base/klass._$klass\n             * @param  {Function} arg0 - 父类\n             * @param  {Boolean}  arg1 - 是否拷贝父类的静态方法，默认拷贝父类静态方法\n             * @return {Object}          扩展类的prototype对象\n             */\n            _Klass._$extend = function(_super,_static){\n                if (_isNotFunction(_super)){\n                    return;\n                }\n                // for static method\n                var _this = this;\n                if (_static!==!1){\n                    _u.__forIn(_super,function(v,k){\n                        if (!_isNotFunction(v)){\n                            _this[k] = v;\n                        }\n                    });\n                }\n                // do inherit\n                this._$super = _super;\n                var _parent = function(){};\n                _parent.prototype = _super.prototype;\n                this.prototype = new _parent();\n                this.prototype.constructor = this;\n                // for super method call\n                var _stack = [],\n                    _phash = {};\n                var _doUpdateCache = function(_method,_klass){\n                    var _result = _doFindIn(_method,_klass);\n                    if (!_result) return;\n                    // save state\n                    if (_stack[_stack.length-1]!=_result.name){\n                        _stack.push(_result.name);\n                    }\n                    _phash[_result.name] = _result.klass._$super;\n                    return _result.name;\n                };\n                this.prototype.__super = function(){\n                    var _name = _stack[_stack.length-1],\n                        _method = arguments.callee.caller;\n                    if (!_name){\n                        _name = _doUpdateCache(_method,this.constructor);\n                    }else{\n                        var _parent = _phash[_name].prototype;\n                        // switch caller name\n                        if (!_parent.hasOwnProperty(_name)||\n                            _method!=_parent[_name]){\n                            _name = _doUpdateCache(_method,this.constructor);\n                        }else{\n                            // other method in current parent\n                            _phash[_name] = _phash[_name]._$super;\n                        }\n                    }\n                    // call parent method\n                    var _ret = _phash[_name].prototype[_name].apply(this,arguments);\n                    // exit super\n                    if (_name==_stack[_stack.length-1]){\n                        _stack.pop();\n                        delete _phash[_name];\n                    }\n                    return _ret;\n                };\n\n                if (CMPT){\n                    var _pro = this.prototype;\n                    _pro.__supInit      = _pro.__super;\n                    _pro.__supReset     = _pro.__super;\n                    _pro.__supDestroy   = _pro.__super;\n                    _pro.__supInitNode  = _pro.__super;\n                    _pro.__supDoBuild   = _pro.__super;\n                    _pro.__supOnShow    = _pro.__super;\n                    _pro.__supOnHide    = _pro.__super;\n                    _pro.__supOnRefresh = _pro.__super;\n                    this._$supro = _super.prototype;\n                }\n\n                return this.prototype;\n            };\n            return _Klass;\n        };\n    })();\n\n    if (CMPT){\n        NEJ.C = _p._$klass;\n        NEJ.copy(this.NEJ,NEJ);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/base/platform/config.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/global',\n    'base/util'\n],function(NEJ,_u,_p,_o,_f,_r){\n    var _cache = {};\n    /*\n     * URL地址转源信息\n     * http://a.b.com:8080/a/bc/ -> http://a.b.com:8080\n     * @param  {String} URL地址\n     * @return {String} 源信息\n     */\n    _p.__url2host = (function(){\n        var _reg = /^([\\w]+?:\\/\\/.*?(?=\\/|$))/i;\n        return function(_url){\n            _url = _url||'';\n            // fix relative protocol url\n            if (_url.indexOf('//')===0){\n                _url = location.protocol+_url;\n            }\n            if (_reg.test(_url))\n                return RegExp.$1;\n            return location.protocol+'//'+location.host;\n        };\n    })();\n    /**\n     * 设置NEJ配置信息\n     * @param  {String}   配置标识\n     * @param  {Variable} 配置信息\n     * @return {Void}\n     */\n    _p.__set = function(_key,_value){\n        _cache[_key] = _value;\n    };\n    /**\n     * 获取NEJ配置信息\n     * @param  {String}   配置标识\n     * @return {Variable} 配置信息\n     */\n    _p.__get = function(_key){\n        return _cache[_key];\n    };\n\n    // init\n    /*\n     * 初始化配置信息\n     * @param  {Object} 配置信息\n     * @return {Void}\n     */\n    var _doInit = (function(){\n        var _conf = {\n            'portrait':{name:'portrait',dft:'portrait/'},\n            'ajax.swf':{name:'ajax',dft:'nej_proxy_flash.swf'},\n            'chart.swf':{name:'chart',dft:'nej_flex_chart.swf'},\n            'audio.swf':{name:'audio',dft:'nej_player_audio.swf'},\n            'video.swf':{name:'video',dft:'nej_player_video.swf'},\n            'clipboard.swf':{name:'clipboard',dft:'nej_clipboard.swf'},\n            'upload.image.swf':{name:'uploadimage',dft:'nej_upload_image.swf'}\n        };\n        var _doInitProxy = function(_list){\n            var _map = {};\n            if (!_list||!_list.length){\n                return _map;\n            }\n            for(var i=0,l=_list.length,_path;i<l;i++){\n                _path = _list[i];\n                if (_path.indexOf('://')>0)\n                    _map[_p.__url2host(_path)] = _path;\n            }\n            return _map;\n        };\n        return function(_config){\n            // check path config\n            _p.__set('root',_config.root||'/res/');\n            var _root = _p.__get('root');\n            _u._$loop(_conf,function(v,k,m){\n                _p.__set(k,_config[v.name]||(_root+v.dft));\n            });\n            // csrf config\n            var _csrf = _config.p_csrf;\n            if (_csrf===!0){\n                _csrf = {\n                    cookie:'AntiCSRF',\n                    param:'AntiCSRF'\n                };\n            }\n            _csrf = _csrf || _o;\n            _p.__set('csrf',{\n                param:_csrf.param||'',\n                cookie:_csrf.cookie||''\n            });\n            // ajax by frame proxy\n            _p.__set('frames',_doInitProxy(_config.p_frame));\n            // ajax by flash proxy\n            _p.__set('flashs',_doInitProxy(_config.p_flash));\n        };\n    })();\n    _doInit(this.NEJ_CONF||_o);\n\n    return _p;\n});\n"
  },
  {
    "path": "src/base/platform/config.patch.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    './config.js',\n    'base/platform'\n],function(_h,_m,_p,_o,_f,_r){\n    // for ie\n    NEJ.patch('TR',function(){\n        _h.__set(\n            'storage.swf',\n            (this.NEJ_CONF||_o).storage||\n            (_h.__get('root')+'nej_storage.swf')\n        );\n    });\n    // for ie7- data uri not available\n    NEJ.patch('TR<=3.0',function(){\n        _h.__set(\n            'blank.png',\n            (this.NEJ_CONF||_o).blank||\n            (_h.__get('root')+'nej_blank.gif')\n        );\n    });\n\n    return _h;\n});\n"
  },
  {
    "path": "src/base/platform/element.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/util',\n    'base/platform'\n],function(_u,_m,_p,_o,_f,_r){\n    /**\n     * 从DocumentFragment中取指定ID的节点\n     * @param  {Document} 文档对象\n     * @param  {String}   节点标识\n     * @return {Node}     指定标识的节点\n     */\n    _p.__getElementById = function(_fragment,_id){\n        if (!!_fragment.getElementById){\n            return _fragment.getElementById(''+_id);\n        }\n        try{\n            return _fragment.querySelector('#'+_id);\n        }catch(e){\n            return null;\n        }\n    };\n    /**\n     * 取节点的子节点列表\n     * @param  {Node}  节点ID或者对象\n     * @return {Array} 子节点列表\n     */\n    _p.__getChildren = function(_element){\n        return _u._$object2array(\n            _element.children||_element.childNodes\n        );\n    };\n    /**\n     * 根据类名取节点列表\n     * @param  {Node}   节点ID或者对象\n     * @param  {String} 类名\n     * @return {Array}  节点列表\n     */\n    _p.__getElementsByClassName = function(_element,_class){\n        return _u._$object2array(_element.getElementsByClassName(_class));\n    };\n    /**\n     * 取下一个兄弟节点\n     * @param  {Node}  节点对象\n     * @return {Node}  节点\n     */\n    _p.__nextSibling = function(_element){\n        return _element.nextElementSibling;\n    };\n    /**\n     * 取上一个兄弟节点\n     * @param  {Node}  节点对象\n     * @return {Node}  节点\n     */\n    _p.__previousSibling = function(_element){\n        return _element.previousElementSibling;\n    };\n    /**\n     * 设置、获取数据\n     * @param {Node}     节点\n     * @param {String}   标识\n     * @param {Variable} 值\n     */\n    _p.__dataset = function(_element,_name,_value){\n        _element.dataset = _element.dataset||{};\n        if (_value!==undefined){\n            _element.dataset[_name] = _value;\n        }\n        return _element.dataset[_name];\n    };\n    /**\n     * 取节点属性值\n     * @param  {Node}   节点\n     * @param  {String} 属性名\n     * @return {String} 属性值\n     */\n    _p.__getAttribute = function(_element,_name){\n        if ('getAttribute' in _element){\n            return _element.getAttribute(_name);\n        }\n    };\n    /**\n     * 将dom节点转为xml串\n     * @param  {Node}   节点\n     * @return {String} XML代码\n     */\n    _p.__serializeDOM2XML = function(_dom){\n        return new XMLSerializer().serializeToString(_dom)||'';\n    };\n    /**\n     * 将xml转为dom节点\n     * @param  {String} XML代码\n     * @return {Node}   节点\n     */\n    _p.__parseDOMFromXML = function(_xml){\n        var _root = new DOMParser()\n                       .parseFromString(_xml,'text/xml')\n                       .documentElement;\n        return _root.nodeName=='parsererror'?null:_root;\n    };\n    /**\n     * 节点占全屏\n     * @param  {Node}   节点\n     * @param  {Object} 视窗模型\n     * @return {Void}\n     */\n    _p.__fullScreen = function(){\n        // use css fixed position\n    };\n    /**\n     * 为节点增加用于盖select/flash等控件的层\n     * @param  {Node} 节点\n     * @return {Void}\n     */\n    _p.__mask = function(){\n        // do nothing\n    };\n    /**\n     * 去除用于盖select/flash等控件的层\n     * @param  {Node} 节点\n     * @return {Void}\n     */\n    _p.__unmask = function(){\n        // do nothing\n    };\n    // variables\n    var _ospt = _m._$SUPPORT,\n        _opfx = _m._$KERNEL.prefix;\n    /**\n     * 指定名称是否在配置表中\n     * @param  {String}  名称\n     * @param  {Object}  配置表\n     * @return {Boolean} 是否命中\n     */\n    _p.__isMatchedName = (function(){\n        var _reg = /^([a-z]+?)[A-Z]/;\n        return function(_name,_map){\n            return !!(_map[_name]||(_reg.test(_name)&&_map[RegExp.$1]));\n        };\n    })();\n    /**\n     * 样式名称做前缀增强\n     * @param  {String}  名称\n     * @return {Boolean} 是否需要前缀增强\n     */\n    _p.__isNeedPrefixed = (function(){\n        var _pmap = _u._$array2object([\n            'animation','transform','transition',\n            'appearance','userSelect','box','flex','column'\n        ]);\n        return function(_name){\n            return _p.__isMatchedName(_name,_pmap);\n        };\n    })();\n    /**\n     * 格式化样式属性名称\n     * border-width -> borderWidth\n     * @param  {String} 样式样式名\n     * @return {String} 格式化后样式名\n     */\n    _p.__fmtStyleName = (function(){\n        var _reg = /-([a-z])/g;\n        return function(_name){\n            _name = _name||'';\n            return _name.replace(_reg,function($1,$2){\n                return $2.toUpperCase();\n            });\n        };\n    })();\n    /**\n     * 针对样式名称做格式化及前缀增强\n     * @param  {String} 样式名\n     * @return {String} 增强后的样式名\n     */\n    _p.__getStyleName = (function(){\n        var _reg = /^[a-z]/,\n            _prefix = _opfx.css||'';\n        return function(_name){\n            _name = _p.__fmtStyleName(_name);\n            if (!_p.__isNeedPrefixed(_name)){\n                return _name;\n            }\n            // add prefix\n            // userSelect -> webkitUserSelect\n            return _prefix+_name.replace(_reg,function($1){\n                return $1.toUpperCase();\n            });\n        };\n    })();\n    /**\n     * 取样式值\n     * @param  {String|Node} 节点\n     * @param  {String}      样式名称\n     * @return {Variable}    样式值\n     */\n    _p.__getStyleValue = function(_element,_name){\n        var _current = window.getComputedStyle(_element,null);\n        return _current[_p.__getStyleName(_name)]||'';\n    };\n    /**\n     * 设置样式\n     * @param  {String|Node} 节点\n     * @param  {String}      样式名称\n     * @param  {String}      样式值\n     * @return {Void}\n     */\n    _p.__setStyleValue = function(_element,_name,_value){\n        _element.style[_p.__getStyleName(_name)] = _value;\n    };\n    /**\n     * 取样式变换矩阵对象\n     * @param  {String}    变换信息\n     * @return {CSSMatrix} 变换矩阵对象\n     */\n    _p.__getCSSMatrix = (function(){\n        var _reg0 = /\\((.*?)\\)/,\n            _reg1 = /\\s*,\\s*/,\n            _klss = ['CSSMatrix',_opfx.clz+'CSSMatrix'],\n            _list = ['m11','m12','m21','m22','m41','m42'];\n        // matrix(1,2,3,4,5,6)\n        // -> {m11:1,m12:2,m21:3,m22:4,m41:5,m42:6}\n        var _doParse = function(_matrix){\n            var _obj = {};\n            if (_reg0.test(_matrix||'')){\n                // 11,12,21,22,41,42\n                _u._$forEach(\n                    RegExp.$1.split(_reg1),\n                    function(_value,_index){\n                        _obj[_list[_index]] = _value;\n                    }\n                );\n            }\n            return _obj;\n        };\n        return function(_matrix){\n            var _mtrx;\n            _u._$forIn(_klss,function(_name){\n                if (!!this[_name]){\n                    _mtrx = new this[_name](_matrix||'');\n                    return !0;\n                }\n            });\n            return !_mtrx?_doParse(_matrix):_mtrx;\n        };\n    })();\n    /**\n     * 注入样式\n     * @param  {Node}   样式节点\n     * @param  {String} 样式内容\n     * @return {Void}\n     */\n    _p.__injectCSSText = function(_style,_css){\n        _style.textContent = _css;\n    };\n    /**\n     * 对样式进行预处理\n     * @param  {String} 待处理样式内容\n     * @return {String} 处理后样式内容\n     */\n    _p.__processCSSText = (function(){\n        var _reg0 = /\\$<(.*?)>/gi,\n            _reg1 = /\\{(.*?)\\}/g,\n            _pfx = '-'+_opfx.css.toLowerCase()+'-',\n            _2dmap = {\n                scale:'scale({x|1},{y|1})',\n                rotate:'rotate({a})',\n                translate:'translate({x},{y})',\n                matrix:'matrix({m11},{m12},{m21},{m22},{m41},{m42})'\n            },\n            _3dmap  = {\n                scale:'scale3d({x|1},{y|1},{z|1})',\n                rotate:'rotate3d({x},{y},{z},{a})',\n                translate:'translate3d({x},{y},{z})',\n                matrix:'matrix3d({m11},{m12},{m13},{m14},{m21},{m22},{m23},{m24},{m31},{m32},{m33|1},{m34},{m41},{m42},{m43},{m44|1})'\n            };\n        // merge template and data\n        var _getTransformValue = function(_tpl,_map){\n            _map = _map||_o;\n            return _tpl.replace(_reg1,function($1,$2){\n                var _arr = $2.split('|');\n                return _map[_arr[0]]||_arr[1]||'0';\n            });\n        };\n        // process transform value\n        _p.__processTransformValue = function(_name,_data){\n            var _tpl = (!_ospt.css3d?_2dmap:_3dmap)[_name.trim()];\n            if (!!_tpl){\n                return _getTransformValue(_tpl,_data);\n            }\n            return '';\n        };\n        return function(_css){\n            if (!_css.replace){\n                return _css;\n            }\n            return _css.replace(_reg0,function($1,$2){\n                // prefix for css3\n                if ($2==='vendor'){\n                    return _pfx;\n                }\n                // parse 3D value\n                var _arr = ($2||'').split('|');\n                return _p.__processTransformValue(\n                    _arr[0],_u._$query2object(_arr[1])\n                )||$1;\n            });\n        };\n    })();\n    /**\n     * 追加CSS规则\n     * @param  {Node}    样式节点\n     * @param  {String}  单条样式规则\n     * @return {CSSRule} 样式规则对象\n     */\n    _p.__appendCSSText = function(_element,_css){\n        var _sheet = _element.sheet,\n            _length = _sheet.cssRules.length;\n        _sheet.insertRule(_css,_length);\n        return _sheet.cssRules[_length];\n    };\n    /**\n     * 取待验证的样式列表\n     * @param  {String} 样式，多个以空格分隔\n     * @return {Array}  样式列表\n     */\n    _p.__getClassList = (function(){\n        var _reg = /\\s+/;\n        return function(_class){\n            _class = (_class||'').trim();\n            return !!_class?_class.split(_reg):null;\n        };\n    })();\n    /**\n     * 操作样式\n     * @param  {Node}   节点\n     * @param  {String} 操作\n     * @param  {String} 样式\n     * @return {Void}\n     */\n    _p.__processClassName = function(_element,_type,_class){\n        if (_type=='replace'){\n            _p.__processClassName(\n                _element,'remove',_class\n            );\n            _p.__processClassName(\n                _element,'add',arguments[3]\n            );\n            return;\n        }\n        _u._$forEach(\n            _p.__getClassList(_class),\n            function(_clazz){\n                _element.classList[_type](_clazz);\n            }\n        );\n    };\n    /**\n     * 检测节点是否包含指定样式，多个样式用空格分隔，检测时包含其中之一即表示包含\n     * @param  {Node}    节点ID或者对象\n     * @param  {String}  样式串\n     * @return {Boolean} 是否含指定样式\n     */\n    _p.__hasClassName = function(_element,_class){\n        var _list = _element.classList;\n        if (!_list||!_list.length){\n            return !1;\n        }\n        return _u._$indexOf(\n            _p.__getClassList(_class),\n            function(_clazz){\n                return _list.contains(_clazz);\n            }\n        )>=0;\n    };\n    // for init\n    (function(){\n        if (!_ospt.css3d){\n            var _matrix = _p.__getCSSMatrix();\n            _ospt.css3d = !!_matrix&&_matrix.m41!=null;\n        }\n    })();\n\n    return _p;\n});\n"
  },
  {
    "path": "src/base/platform/element.patch.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    './element.js',\n    'base/platform',\n    'base/util'\n],function(_h,_m,_u,_p,_o,_f,_r){\n    // for ie\n    NEJ.patch('TR',function(){\n        /**\n         * 取节点的子节点列表\n         * @param  {Node} _element 节点ID或者对象\n         * @return {Array}         子节点列表\n         */\n        _h.__getChildren = _h.__getChildren._$aop(\n            function(_event){\n                var _element = _event.args[0];\n                if (!!_element.children) return;\n                // hack children\n                _event.stopped = !0;\n                var _result = [];\n                _u._$forEach(\n                    _element.childNodes,\n                    function(_node){\n                        if (_node.nodeType==1){\n                            _result.push(_node);\n                        }\n                    }\n                );\n                _event.value = _result;\n            }\n        );\n    });\n    // for ie10-\n    NEJ.patch('TR<=6.0',function(){\n        /**\n         * 设置、获取数据\n         * @param {Node}     节点\n         * @param {String}   标识\n         * @param {Variable} 值\n         */\n        _h.__dataset = (function(){\n            var _dataset = {},\n                _tag = 'data-',\n                _reg = /\\-(.{1})/gi;\n            // init element dataset\n            var _init = function(_element){\n                var _id = _element.id;\n                if (!!_dataset[_id]) return;\n                var _map = {};\n                _u._$forEach(\n                    _element.attributes,\n                    function(_node){\n                        var _key  = _node.nodeName;\n                        if (_key.indexOf(_tag)!=0) return;\n                        _key = _key.replace(_tag,'')\n                                   .replace(_reg,function($1,$2){\n                                        return $2.toUpperCase();\n                                   });\n                        _map[_key] = _node.nodeValue||'';\n                    }\n                );\n                _dataset[_id] = _map;\n            };\n            return function(_element,_key,_value){\n                _init(_element);\n                var _set = _dataset[_element.id];\n                if (_value!==undefined){\n                    _set[_key] = _value;\n                }\n                return _set[_key];\n            };\n        })();\n    });\n    // for ie9-\n    NEJ.patch('TR<=5.0',function(){\n        // cache background image\n        try{document.execCommand('BackgroundImageCache',!1,!0);}catch(e){}\n        /**\n         * 注入样式\n         * @param  {Node}   样式节点\n         * @param  {String} 样式内容\n         * @return {Void}\n         */\n        _h.__injectCSSText = (function(){\n            var _max = 30;\n            return _h.__injectCSSText._$aop(function(_event){\n                var _element = _event.args[0];\n                if (!_element.styleSheet) return;\n                _event.stopped = !0;\n                var _css = _event.args[1];\n                // ie9- has 31 style/link limitation\n                var _list = document.styleSheets;\n                if (_list.length>_max){\n                    // bad performance\n                    _element = _list[_max];\n                    _css = _element.cssText + _css;\n                }else{\n                    _element = _element.styleSheet;\n                }\n                _element.cssText = _css;\n            });\n        })();\n        /**\n         * 取待验证的样式正则表达式\n         * @param  {String} 样式，多个以空格分隔\n         * @return {RegExp} 正则表达式\n         */\n        _h.__getClassRegExp = (function(){\n            var _reg = /\\s+/g;\n            return function(_class){\n                _class = (_class||'').trim().replace(_reg,'|');\n                return !_class?null:new RegExp('(\\\\s|^)(?:'+_class+')(?=\\\\s|$)','g');\n            };\n        })();\n        /**\n         * 操作样式\n         * @param  {Node}   节点\n         * @param  {String} 操作\n         * @param  {String} 样式\n         * @return {Void}\n         */\n        _h.__processClassName = function(_element,_type,_class){\n            _class = _class||'';\n            var _name = _element.className||'',\n                _xreg = _h.__getClassRegExp(\n                    _class+' '+(arguments[3]||'')\n                );\n            // remove all calss\n            var _result = _name;\n            if (!!_xreg){\n                _result = _result.replace(_xreg,'');\n            }\n            // parse added class\n            switch(_type){\n                case 'remove':\n                    _class = '';\n                break;\n                case 'replace':\n                    _class = arguments[3]||'';\n                break;\n            }\n            // generate class result\n            _result = (_result+' '+_class).trim();\n            if (_name!=_result){\n                _element.className = _result;\n            }\n        };\n        /**\n         * 检测节点是否包含指定样式，多个样式用空格分隔，检测时包含其中之一即表示包含\n         * @param  {Node}    节点ID或者对象\n         * @param  {String}  样式串\n         * @return {Boolean} 是否含指定样式\n         */\n        _h.__hasClassName = function(_element,_class){\n            var _xreg = _h.__getClassRegExp(_class);\n            if (!!_xreg){\n                return _xreg.test(_element.className||'');\n            }\n            return !1;\n        };\n    });\n    // for ie8-\n    NEJ.patch('TR<=4.0',function(){\n        /**\n         * 根据类名取节点列表\n         * @param  {Node}   节点ID或者对象\n         * @param  {String} 类名\n         * @return {Array}  节点列表\n         */\n        _h.__getElementsByClassName = function(_element,_class){\n            var _result = [],\n                _regexp = new RegExp('(\\\\s|^)(?:'+_class.replace(/\\s+/g,'|')+')(?=\\\\s|$)');\n            _u._$forEach(\n                _element.getElementsByTagName('*'),\n                function(_node){\n                    if (_regexp.test(_node.className)){\n                        _result.push(_node);\n                    }\n                }\n            );\n            return _result;\n        };\n        /**\n         * 取下一个兄弟节点\n         * @param  {Node}  节点对象\n         * @return {Node}  节点\n         */\n        _h.__nextSibling = function(_element){\n            while(_element=_element.nextSibling){\n                if (_element.nodeType==1){\n                    return _element;\n                }\n            }\n        };\n        /**\n         * 取上一个兄弟节点\n         * @param  {Node}  节点对象\n         * @return {Node}  节点\n         */\n        _h.__previousSibling = function(_element){\n            while(_element=_element.previousSibling){\n                if (_element.nodeType==1){\n                    return _element;\n                }\n            }\n        };\n        /**\n         * 将dom节点转为xml串\n         * @param  {Node}   节点\n         * @return {String} XML代码\n         */\n        _h.__serializeDOM2XML = function(_dom){\n            return ('xml' in _dom)?_dom.xml:_dom.outerHTML;\n        };\n        /**\n         * 将xml转为dom节点\n         * @param  {String} XML代码\n         * @return {Node}   节点\n         */\n        _h.__parseDOMFromXML = (function(){\n            // http://blogs.msdn.com/b/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx\n            var _msxml = [\n                'Msxml2.DOMDocument.6.0',\n                'Msxml2.DOMDocument.3.0'\n            ];\n            var _getParser = function(){\n                try{\n                    for(var i=0,l=_msxml.length;i<l;i++){\n                        return new ActiveXObject(_msxml[i]);\n                    }\n                }catch(ex){\n                    return null;\n                }\n            };\n            return function(_xml){\n                var _parser = _getParser();\n                if (!!_parser&&\n                      _parser.loadXML(_xml)&&\n                     !_parser.parseError.errorCode){\n                    return _parser.documentElement;\n                }\n                return null;\n            };\n        })();\n        /**\n         * 取样式值\n         * @param  {String|Node} 节点\n         * @param  {String}      样式名称\n         * @return {Variable}    样式值\n         */\n        _h.__getStyleValue = (function(){\n            var _reg0 = /opacity\\s*=\\s*([\\d]+)/i;\n            var _fmap = {\n                // get opacity from filter:alpha(opacity=50)\n                opacity:function(_style){\n                    var _result = 0;\n                    if (_reg0.test(_style.filter||'')){\n                        _result = parseFloat(RegExp.$1)/100;\n                    }\n                    return _result;\n                }\n            };\n            return function(_element,_name){\n                var _current = _element.currentStyle,\n                    _func = _fmap[_name];\n                if (!!_func){\n                    return _func(_current);\n                }\n                return _current[_h.__getStyleName(_name)]||'';\n            };\n        })();\n        /**\n         * 设置样式\n         * @param  {String|Node} 节点\n         * @param  {String}      样式名称\n         * @param  {String}      样式值\n         * @return {Void}\n         */\n        _h.__setStyleValue = (function(){\n            var _fmap = {\n                // opacity -> filter:alpha(opacity=50)\n                opacity:function(_element,_value){\n                    _element.style.filter = 'alpha(opacity='+_value*100+')';\n                }\n            };\n            return function(_element,_name,_value){\n                var _func = _fmap[_name];\n                if (!!_func){\n                    _func(_element,_value);\n                }else{\n                    _element.style[_h.__getStyleName(_name)] = _value;\n                }\n            };\n        })();\n        /**\n         * 追加CSS规则\n         * @param  {Node}    样式节点\n         * @param  {String}  单条样式规则\n         * @return {CSSRule} 样式规则对象\n         */\n        _h.__appendCSSText = function(_element,_css){\n            var _sheet = _element.styleSheet,\n                _length = _sheet.rules.length,\n                _arr = _css.split(/[\\{\\}]/);\n            _sheet.addRule(_arr[0],_arr[1],_length);\n            return _sheet.rules[_length];\n        };\n     });\n    // for ie7-\n    NEJ.patch('TR<=3.0',function(){\n        /**\n         * 取节点属性值\n         * @param  {Node}   节点\n         * @param  {String} 属性名\n         * @return {String} 属性值\n         */\n        _h.__getAttribute =\n        _h.__getAttribute._$aop(null,function(_event){\n            // fix ie7 maxlength default value 2147483647\n            var _args = _event.args;\n            if (_args[1]=='maxlength'&&\n                _event.value==2147483647){\n                _event.value = null;\n            }\n        });\n    });\n    // for ie6-\n    NEJ.patch('TR<=2.0',function(){\n        /**\n         * 节点占全屏\n         * @param  {Node}   节点\n         * @param  {Object} 视窗模型\n         * @return {Void}\n         */\n        _h.__fullScreen = function(_element,_viewport){\n            var _style = _element.style;\n            _style.width = _viewport.scrollWidth+'px';\n            _style.height = _viewport.scrollHeight+'px';\n        };\n        /**\n         * 为节点增加用于盖select/flash等控件的层\n         * @param  {Node} 节点\n         * @return {Void}\n         */\n        _h.__mask = (function(){\n            var _cache = {};\n            // remove mask\n            _h.__unmask = function(_element){\n                var _id = _element.id,\n                    _mask = _cache[_id];\n                if (!!_mask){\n                    delete _cache[_id];\n                    _mask.parentNode.removeChild(_mask);\n                }\n            };\n            // append mask\n            return function(_element){\n                var _id = _element.id,\n                    _mask = _cache[_id];\n                // create mask\n                if (!_mask){\n                    _mask = document.createElement('iframe');\n                    _mask.style.position = 'absolute';\n                    _cache[_id] = _mask;\n                }\n                // sync mask size\n                var _style1 = _mask.style,\n                    _style0 = _element.style;\n                _style1.top = (parseInt(_style0.top)||0)+'px';\n                _style1.left = (parseInt(_style0.left)||0)+'px';\n                _style1.width = _element.offsetWidth+'px';\n                _style1.height = _element.offsetHeight+'px';\n                _element.insertAdjacentElement('beforeBegin',_mask);\n                return _mask;\n            };\n        })();\n    });\n    // for firefox\n    NEJ.patch('GR',function(){\n        if (!_m._$SUPPORT.css3d){\n            _m._$SUPPORT.css3d = 'MozPerspective' in document.body.style;\n        }\n        if (!('insertAdjacentElement' in document.body)){\n            HTMLElement.prototype.insertAdjacentElement = function(_where,_element){\n                if (!_where||!_element) return;\n                switch(_where){\n                    case 'beforeEnd'  :\n                        this.appendChild(_element);\n                    return;\n                    case 'beforeBegin':\n                        this.parentNode.insertBefore(_element,this);\n                    return;\n                    case 'afterBegin' :\n                        !this.firstChild\n                        ?this.appendChild(_element)\n                        :this.insertBefore(_element,this.firstChild);\n                    return;\n                    case 'afterEnd'   :\n                        !this.nextSibling\n                        ?this.parentNode.appendChild(_element)\n                        :this.parentNode.insertBefore(_element,this.nextSibling);\n                    return;\n                }\n            };\n        }\n        if (!('innerText' in document.body)){\n            HTMLElement.prototype['__defineGetter__'](\"innerText\",function(){return this.textContent;});\n            HTMLElement.prototype['__defineSetter__'](\"innerText\",function(_content){this.textContent = _content;});\n        }\n    });\n\n    return _h;\n});\n"
  },
  {
    "path": "src/base/platform/event.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/util',\n    'base/platform'\n],function(_u,_m,_p,_o,_f,_r){\n    /**\n     * 验证事件信息\n     * @param  {Node}     节点\n     * @param  {String}   事件类型\n     * @param  {Function} 处理函数\n     * @return {Object}   验证后事件信息 type/handler\n     */\n    _p.__checkEvent = (function(){\n            // need change event name\n        var _tmap = {\n                touchstart:'mousedown',\n                touchmove:'mousemove',\n                touchend:'mouseup'\n            },\n            // need prefix\n            _pfix = _m._$KERNEL.prefix,\n            _emap = {\n                transitionend:'TransitionEnd',\n                animationend:'AnimationEnd',\n                animationstart:'AnimationStart',\n                animationiteration:'AnimationIteration',\n                visibilitychange:'visibilitychange',\n                fullscreenchange:'fullscreenchange'\n            };\n        var _fmap = {\n            enter:function(_element,_type,_handler){\n                var _result = {\n                    type:'keypress'\n                };\n                if (!!_handler){\n                    _result.handler = function(_event){\n                        if (_event.keyCode===13){\n                            _handler.call(_element,_event);\n                        }\n                    };\n                }\n                return _result;\n            }\n        };\n        var _doPrefix = function(_name){\n            return (_pfix.evt||_pfix.pro)+_name;\n        };\n        return function(_element,_type,_handler){\n            var _result = {\n                type:_type,\n                handler:_handler\n            };\n            if (!(('on'+_type) in _element)){\n                // check name convert\n                var _name = _tmap[_type];\n                if (!!_name){\n                    _result.type = _name;\n                    return _result;\n                }\n                // check prefix complete\n                var _name = _emap[_type];\n                if (!!_name){\n                    _result.type = _doPrefix(_name);\n                    return _result;\n                }\n                // check event update\n                var _func = _fmap[_type];\n                if (!!_func){\n                    return _func.apply(null,arguments);\n                }\n            }\n            return _result;\n        };\n    })();\n    /**\n     * 添加事件\n     * @param  {Node}     节点\n     * @param  {String}   事件\n     * @param  {Function} 处理函数\n     * @param  {Boolean}  是否捕捉阶段\n     * @return {Void}\n     */\n    _p.__addEvent = function(){\n        var _args = arguments;\n        if (DEBUG){\n            if (!(('on'+_args[1]) in _args[0])){\n                console.log('not support event['+_args[1]+'] for '+_args[0]);\n            }\n        }\n        _args[0].addEventListener(\n            _args[1],_args[2],_args[3]\n        );\n    };\n    /**\n     * 删除事件\n     * @param  {Node}     节点\n     * @param  {String}   事件\n     * @param  {Function} 处理函数\n     * @param  {Boolean}  是否捕捉阶段\n     * @return {Void}\n     */\n    _p.__delEvent = function(){\n        var _args = arguments;\n        _args[0].removeEventListener(\n            _args[1],_args[2],_args[3]\n        );\n    };\n    /**\n     * 触发对象的某个事件\n     * @param  {String|Node} 节点ID或者对象\n     * @param  {String}      鼠标事件类型\n     * @return {Void}\n     */\n    _p.__dispatchEvent = function(_element,_type,_options){\n        var _event = document.createEvent('Event');\n        _event.initEvent(_type,!0,!0);\n        _u._$merge(_event,_options);\n        _element.dispatchEvent(_event);\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/base/platform/event.patch.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    './event.js',\n    'base/util'\n],function(_h,_u,_p,_o,_f,_r){\n    // for ie10+\n    NEJ.patch('TR>=6.0',function(){\n        /**\n         * 验证事件信息\n         * @param  {Node}     节点\n         * @param  {String}   事件类型\n         * @param  {Function} 处理函数\n         * @return {Object}   验证后事件信? type/handler\n         */\n        _h.__checkEvent = (function(){\n            var _emap = {\n                touchcancel:'MSPointerCancel',\n                touchstart:'MSPointerDown',\n                touchmove:'MSPointerMove',\n                touchend:'MSPointerUp',\n                fullscreenchange:'MSFullscreenChange'\n            };\n            return _h.__checkEvent._$aop(function(_event){\n                var _args = _event.args;\n                // check event convert\n                var _name = _emap[_args[1]];\n                if (!!_name){\n                    _event.stopped = !0;\n                    _event.value = {\n                        type:_name,\n                        handler:_args[2]\n                    };\n                }\n            });\n        })();\n    });\n    // for ie9\n    NEJ.patch('TR==5.0',function(){\n        /**\n         * 验证事件信息\n         * @param  {Node}     节点\n         * @param  {String}   事件类型\n         * @param  {Function} 处理函数\n         * @return {Object}   验证后事件信? type/handler\n         */\n        _h.__checkEvent = (function(){\n            var _vmap = {};\n            var _fmap = {\n                input:function(_element,_type,_handler){\n                    // for check type only\n                    if (!_handler){\n                        return {type:_type};\n                    }\n                    // fix input backspace/delete/ctrl+x bug\n                    return {\n                        type:_type,\n                        handler:function(_event){\n                            var _id = _element.id;\n                            _vmap[_id] = _element.value;\n                            _handler.call(_element,_event);\n                        },\n                        link:[[\n                            document,'selectionchange',\n                            function(_event){\n                                var _id = _element.id;\n                                if (_element!=document.activeElement){\n                                    delete _vmap[_id];\n                                    return;\n                                }\n                                if (_vmap[_id]!==_element.value){\n                                    _vmap[_id] = _element.value;\n                                    _handler.call(_element,_event);\n                                }\n                            }\n                        ]]\n                    };\n                }\n            };\n            return _h.__checkEvent._$aop(function(_event){\n                var _args = _event.args;\n                // check event update\n                var _func = _fmap[_args[1]];\n                if (!!_func){\n                    _event.stopped = !0;\n                    _event.value = _func.apply(null,_args);\n                }\n            });\n        })();\n    });\n    // for ie9+\n    NEJ.patch('TR>=5.0',function(){\n        // must use attach/detach for event\n        var _attached = {\n            'propertychange':1\n        };\n        /**\n         * 添加事件\n         * @param  {Node}     节点\n         * @param  {String}   事件\n         * @param  {Function} 处理函数\n         * @param  {Boolean}  是否捕捉阶段\n         * @return {Void}\n         */\n        _h.__addEvent = \n        _h.__addEvent._$aop(function(_event){\n            var _args = _event.args;\n            if (_attached[_args[1]]!=null&&!!_args[0].attachEvent){\n                _event.stopped = !0;\n                _args[0].attachEvent('on'+_args[1],_args[2]);\n            }\n        });\n        /**\n         * 删除事件\n         * @param  {Node}     节点\n         * @param  {String}   事件\n         * @param  {Function} 处理函数\n         * @param  {Boolean}  是否捕捉阶段\n         * @return {Void}\n         */\n        _h.__delEvent = \n        _h.__delEvent._$aop(function(_event){\n            var _args = _event.args,\n                _alias = _attached[_args[1]];\n            if (_attached[_args[1]]!=null&&!!_args[0].detachEvent){\n                _event.stopped = !0;\n                _args[0].detachEvent('on'+_args[1],_args[2]);\n            }\n        });\n    });\n    // for ie8-\n    NEJ.patch('TR<=4.0',function(){\n        /**\n         * 验证事件信息\n         * @param  {Node}     节点\n         * @param  {String}   事件类型\n         * @param  {Function} 处理函数\n         * @return {Object}   验证后事件信? type/handler\n         */\n        _h.__checkEvent = (function(){\n            var _lmap = {};\n            var _fmap = {\n                input:function(_element,_type,_handler){\n                    var _result = {\n                        type:'propertychange'\n                    };\n                    if (!!_handler){\n                        var _id = _element.id;\n                        var _hack = function(_event){\n                            if (!!_element.value&&!_lmap['x-'+_id]){\n                                _lmap['x-'+_id] = !0;\n                                _handler.call(_element,_event);\n                            }\n                        };\n                        _result.handler = function(_event){\n                            // for input.value or textarea.value\n                            if (('value' in _element)&&\n                                _event.propertyName=='value'){\n                                // lock cycle trigger\n                                if (!!_lmap[_id]){\n                                    return;\n                                }\n                                _lmap[_id] = !0;\n                                _handler.call(_element,_event);\n                                delete _lmap[_id];\n                            }\n                        };\n                        _result.link = [\n                            [_element,'keyup',_hack],\n                            [_element,'mouseup',_hack],\n                            [_element,'mousemove',_hack]\n                        ];\n                        _result.destroy = function(){\n                            delete _lmap[_id];\n                            delete _lmap['x-'+_id];\n                        };\n                    }\n                    return _result;\n                },\n                load:function(_element,_type,_handler){\n                    var _result = {\n                        type:'readystatechange'\n                    };\n                    if (!!_handler){\n                        _result.handler = function(_event){\n                            if (_element.readyState=='loaded'||\n                                _element.readyState=='complete'){\n                                _handler.call(_element,_event);\n                            }\n                        };\n                    }\n                    return _result;\n                }\n            };\n            return _h.__checkEvent._$aop(function(_event){\n                var _args = _event.args;\n                // check event update\n                var _func = _fmap[_args[1]];\n                if (!!_func){\n                    _event.stopped = !0;\n                    _event.value = _func.apply(null,_args);\n                }\n                // use element for this in handler\n                if (!!_args[2]){\n                    _args[2] = _args[2]._$bind(_args[0]);\n                }\n            });\n        })();\n        /**\n         * 添加事件\n         * @param  {Node}     节点\n         * @param  {String}   事件\n         * @param  {Function} 处理函数\n         * @param  {Boolean}  是否捕捉阶段\n         * @return {Void}\n         */\n        _h.__addEvent = function(){\n            var _args = arguments;\n            if (DEBUG){\n                if (!(('on'+_args[1]) in _args[0])){\n                    console.log('not support event['+_args[1]+'] for '+_args[0]);\n                }\n            }\n            _args[0].attachEvent('on'+_args[1],_args[2]);\n        };\n        /**\n         * 删除事件\n         * @param  {Node}     节点\n         * @param  {String}   事件\n         * @param  {Function} 处理函数\n         * @param  {Boolean}  是否捕捉阶段\n         * @return {Void}\n         */\n        _h.__delEvent = function(){\n            var _args = arguments;\n            _args[0].detachEvent('on'+_args[1],_args[2]);\n        };\n        /**\n         * 触发对象的某个事?\n         * @param  {String|Node} 节点ID或?对?\n         * @param  {String}      鼠标事件类型\n         * @return {Void}\n         */\n        _h.__dispatchEvent = (function(){\n            var _omap = {\n                propertychange:{propertyName:'value'}\n            };\n            return function(_element,_type,_options){\n                var _event = document.createEventObject();\n                try{\n                    _u._$merge(_event,_omap[_type],_options);\n                    _element.fireEvent('on'+_type,_event);\n                }catch(ex){\n                    // ignore unrecognized event name\n                    console.error(ex.message);\n                    console.error(ex.stack);\n                }\n            };\n        })();\n    });\n    // for firefox\n    NEJ.patch('GR',function(){\n        /**\n         * 验证事件信息\n         * @param  {Node}     节点\n         * @param  {String}   事件类型\n         * @param  {Function} 处理函数\n         * @return {Object}   验证后事件信? type/handler\n         */\n        _h.__checkEvent = (function(){\n            var _nreg = /^(?:transitionend|animationend|animationstart|animationiteration)$/i;\n            var _fmap = {\n                mousewheel:function(_element,_type,_handler){\n                    var _result = {\n                        type:'MozMousePixelScroll'\n                    };\n                    if (!!_handler){\n                        _result.handler = function(_event){\n                            var _delta = _event.detail;\n                            _event.wheelDelta = -_delta;\n                            _event.wheelDeltaY = -_delta;\n                            _event.wheelDeltaX = 0;\n                            _handler.call(_element,_event);\n                        };\n                    }\n                    return _result;\n                }\n            };\n            return _h.__checkEvent._$aop(function(_event){\n                var _args = _event.args;\n                // check animation event\n                if (_nreg.test(_args[1])){\n                    _event.stopped = !0;\n                    _event.value = {\n                        type:_args[1],\n                        handler:_args[2]\n                    };\n                }\n                // check event update\n                var _func = _fmap[_args[1]];\n                if (!!_func){\n                    _event.stopped = !0;\n                    _event.value = _func.apply(null,_args);\n                }\n            });\n        })();\n    });\n\n    return _h;\n});\n"
  },
  {
    "path": "src/base/platform/util.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define(function(_p,_o,_f,_r){\n    /**\n     * 遍历对象\n     * @param  {Object}   对象\n     * @param  {Function} 迭代回调\n     * @param  {Object}   回调执行对象\n     * @return {String}   循环中断时的key值\n     */\n    _p.__forIn = function(_obj,_callback,_this){\n        if (!_obj||!_callback){\n            return null;\n        }\n        var _keys = Object.keys(_obj);\n        for(var i=0,l=_keys.length,_key,_ret;i<l;i++){\n            _key = _keys[i];\n            _ret = _callback.call(\n                _this||null,\n                _obj[_key],_key,_obj\n            );\n            if (!!_ret){\n                return _key;\n            }\n        }\n        return null;\n    };\n    /**\n     * 遍历列表\n     * @param  {Array}    列表\n     * @param  {Function} 迭代回调\n     * @param  {Object}   回调执行对象\n     * @return {Void}\n     */\n    _p.__forEach = function(_list,_callback,_this){\n        _list.forEach(_callback,_this);\n    };\n    /**\n     * 集合转数组\n     * @param  {Object} 集合\n     * @return {Array}  数组\n     */\n    _p.__col2array = function(_list){\n        return _r.slice.call(_list,0);\n    };\n    /**\n     * YYYY-MM-DDTHH:mm:ss.sssZ格式时间串转时间戳\n     * @param  {String} 时间串\n     * @return {Number} 时间戳\n     */\n    _p.__str2time = function(_str){\n        return Date.parse(_str);\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/base/platform/util.patch.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    './util.js',\n    'base/platform'\n],function(_h,_m,_p,_o,_f,_r){\n    // for ie8-\n    NEJ.patch('TR<=4.0',function(){\n        /**\n         * 遍历对象\n         * @param  {Object}   对象\n         * @param  {Function} 迭代回调\n         * @param  {Object}   回调执行对象\n         * @return {String}   循环中断时的key值\n         */\n        _h.__forIn = function(_obj,_callback,_this){\n            if (!_obj||!_callback){\n                return;\n            }\n            // iterate\n            var _ret;\n            for(var x in _obj){\n                if (!_obj.hasOwnProperty(x)) continue;\n                _ret = _callback.call(_this,_obj[x],x,_obj);\n                if (!!_ret){\n                    return x;\n                }\n            }\n        };\n        /**\n         * 遍历列表\n         * @param  {Array}    列表\n         * @param  {Function} 迭代回调\n         * @param  {Object}   回调执行对象\n         * @return {Void}\n         */\n        _h.__forEach = function(_list,_callback,_this){\n            for(var i=0,l=_list.length;i<l;i++){\n                _callback.call(_this,_list[i],i,_list);\n            }\n        };\n        /**\n         * 集合转数组\n         * @param  {Object} 集合\n         * @return {Array}  数组\n         */\n        _h.__col2array = function(_list){\n            var _result = [];\n            if (!!_list&&!!_list.length){\n                for(var i=0,l=_list.length;i<l;i++){\n                    _result.push(_list[i]);\n                }\n            }\n            return _result;\n        };\n        /**\n         * YYYY-MM-DDTHH:mm:ss.sssZ格式时间串转时间戳\n         * @param  {String} 时间串\n         * @return {Number} 时间戳\n         */\n        _h.__str2time = (function(){\n            var _reg = /-/g;\n            return function(_str){\n                // only support YYYY/MM/DDTHH:mm:ss\n                return Date.parse(_str.replace(_reg,'/').split('.')[0]);\n            };\n        })();\n    });\n\n    return _h;\n});\n"
  },
  {
    "path": "src/base/platform.js",
    "content": "/*\n * ------------------------------------------\n * 平台接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module base/platform */\nNEJ.define([\n    './global.js'\n],function(NEJ,_p,_o,_f,_r){\n    var _platform  = this.navigator.platform,\n        _useragent = this.navigator.userAgent;\n    /**\n     * 平台判断信息\n     * \n     * ```javascript\n     * NEJ.define([\n     *     'base/platform'\n     * ],function(_m){\n     *     var _is = _m._$IS;\n     *     // 是否MAC系统\n     *     console.log(_is.mac);\n     *     // 是否IPhone\n     *     console.log(_is.iphone);\n     *     // ...\n     * });\n     * ```\n     * \n     * @const    module:base/platform._$IS\n     * @see      module:base/platform._$is\n     * @type     {Object}\n     * @property {Boolean} mac     - 是否Mac系统\n     * @property {Boolean} win     - 是否windows系统\n     * @property {Boolean} linux   - 是否linux系统\n     * @property {Boolean} ipad    - 是否Ipad\n     * @property {Boolean} iphone  - 是否IPhone\n     * @property {Boolean} android - 是否Android系统\n     * @property {Boolean} ios     - 是否IOS系统\n     * @property {Boolean} tablet  - 是否平板\n     * @property {Boolean} desktop - 是否桌面系统\n     */\n    var _is = {\n        mac     : _platform,\n        win     : _platform,\n        linux   : _platform,\n        ipad    : _useragent,\n        ipod    : _useragent,\n        iphone  : _platform,\n        android : _useragent\n    };\n    _p._$IS = _is;\n    for(var x in _is){\n        _is[x] = new RegExp(x,'i').test(_is[x]);\n    }\n    _is.ios = _is.ipad||_is.iphone||_is.ipod;\n    _is.tablet = _is.ipad;\n    _is.desktop = _is.mac||_is.win||(_is.linux&&!_is.android);\n    /**\n     * 判断是否指定平台\n     * \n     * ```javascript\n     * NEJ.define([\n     *     'base/platform'\n     * ],function(_m){\n     *     // 是否MAC系统\n     *     console.log(_m._$is('mac'));\n     *     // 是否iphone\n     *     console.log(_m._$is('iphone'));\n     *     // ...\n     * });\n     * ```\n     * \n     * @method module:base/platform._$is\n     * @see    module:base/platform._$IS\n     * @param  {String} arg0 - 平台名称\n     * @return {Boolean}       是否指定平台\n     */\n    _p._$is = function(_platform){\n        return !!_is[_platform];\n    };\n    // parse kernel information\n    /**\n     * 引擎内核信息\n     * \n     * ```javascript\n     * NEJ.define([\n     *     'base/platform'\n     * ],function(_m){\n     *     var _kernel = _m._$KERNEL;\n     *     // 打印平台信息\n     *     console.log(_kernel.engine);\n     *     console.log(_kernel.release);\n     *     console.log(_kernel.browser);\n     *     console.log(_kernel.version);\n     * });\n     * ```\n     * \n     * @const    module:base/platform._$KERNEL\n     * @type     {Object}\n     * @property {String} engine  - 布局引擎，trident/webkit/gecko/presto...\n     * @property {Number} release - 布局引擎版本\n     * @property {String} browser - 浏览器名称，ie/chrome/safari/opera/firefox/maxthon...\n     * @property {Number} version - 浏览器版本\n     * @property {Object} prefix  - 平台前缀，html5/css3 attribute/method/constructor\n     */\n    var _kernel = {\n        engine:'unknow',\n        release:'unknow',\n        browser:'unknow',\n        version:'unknow',\n        prefix:{css:'',pro:'',clz:''}\n    };\n    _p._$KERNEL  = _kernel;\n    if (/msie\\s+(.*?);/i.test(_useragent)||\n        /trident\\/.+rv:([\\d\\.]+)/i.test(_useragent)){\n        _kernel.engine  = 'trident';\n        _kernel.browser = 'ie';\n        _kernel.version = RegExp.$1;\n        _kernel.prefix  = {css:'ms',pro:'ms',clz:'MS',evt:'MS'};\n        // 4.0-ie8 5.0-ie9 6.0-ie10 7.0-ie11\n        // adjust by document mode setting in develop toolbar\n        var _test = {6:'2.0',7:'3.0',8:'4.0',9:'5.0',10:'6.0',11:'7.0'};\n        _kernel.release = _test[document.documentMode]||\n                          _test[parseInt(_kernel.version)];\n    }else if(/webkit\\/?([\\d.]+?)(?=\\s|$)/i.test(_useragent)){\n        _kernel.engine  = 'webkit';\n        _kernel.release = RegExp.$1||'';\n        _kernel.prefix  = {css:'webkit',pro:'webkit',clz:'WebKit'};\n    }else if(/rv\\:(.*?)\\)\\s+gecko\\//i.test(_useragent)){\n        _kernel.engine  = 'gecko';\n        _kernel.release = RegExp.$1||'';\n        _kernel.browser = 'firefox';\n        _kernel.prefix  = {css:'Moz',pro:'moz',clz:'Moz'};\n        if (/firefox\\/(.*?)(?=\\s|$)/i.test(_useragent))\n            _kernel.version = RegExp.$1||'';\n    }else if(/presto\\/(.*?)\\s/i.test(_useragent)){\n        _kernel.engine  = 'presto';\n        _kernel.release = RegExp.$1||'';\n        _kernel.browser = 'opera';\n        _kernel.prefix  = {css:'O',pro:'o',clz:'O'};\n        if (/version\\/(.*?)(?=\\s|$)/i.test(_useragent))\n            _kernel.version = RegExp.$1||'';\n    }\n    if (_kernel.browser=='unknow'){\n        var _test = ['chrome','maxthon','safari'];\n        for(var i=0,l=_test.length,_name;i<l;i++){\n            if (_test[i] == 'safari') {\n                _name = 'version';\n            } else if (_test[i] == 'chrome') {\n                _name = '[chrome|CriOS]'; // CriOS is Google Chrome for iOS\n            } else {\n                _name = _test[i];\n            }\n            if (new RegExp(_name+'/(.*?)(?=\\\\s|$)','i').test(_useragent)){\n                _kernel.browser = _test[i];\n                _kernel.version = RegExp.$1.trim();\n                break;\n            }\n        }\n    }\n    /**\n     * 引擎特性支持信息\n     * \n     * ```javascript\n     * NEJ.define([\n     *     'base/platform'\n     * ],function(_m){\n     *     var _support = _m._$SUPPORT;\n     *     // 打印平台是否支持CSS3 3D特效\n     *     console.log(_support.css3d);\n     * });\n     * ```\n     * @const    module:base/platform._$SUPPORT\n     * @see      module:base/platform._$support\n     * @type     {Object}\n     * @property {Boolean} css3d  - 是否支持CSS3 3D\n     */\n    _p._$SUPPORT = {};\n    /**\n     * 判断平台是否支持指定特性\n     * \n     * ```javascript\n     * NEJ.define([\n     *     'base/platform'\n     * ],function(_m){\n     *     // 是否支持CSS3 3D特效\n     *     console.log(_m._$support('css3d'));\n     * });\n     * ```\n     * \n     * @method module:base/platform._$support\n     * @see    module:base/platform._$SUPPORT\n     * @param  {String} arg0 - 特性标识\n     * @return {Boolean}       是否支持指定特性\n     */\n    _p._$support = function(_feature){\n        return !!_p._$SUPPORT[_feature];\n    };\n    \n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.p'),_p);\n    }\n    \n    return _p;\n});"
  },
  {
    "path": "src/base/test/config.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>config测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit config test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n \t\t<script src=\"../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./config.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/base/test/config.test.js",
    "content": "window.NEJ_CONF = {\n    'root':'/res/',\n    'p_frame':['http://nei.netease.com/html/nej_proxy_frame.html'],\n    'p_flash':['http://nei.netease.com/proxy/crossdomain.xml']\n}\nvar f = function(){\n    //定义测试模块\n    module(\"config\");\n    var _c = NEJ.P('nej.c'),\n        _p = NEJ.P('nej.p');\n\n    //开始单元测试\n    test('NEJ配置文件测试', function() {\n        var _uri = _c._$getFrameProxy('http://nei.netease.com');\n        equal(_uri,'http://nei.netease.com/html/nej_proxy_frame.html','代理文件地址');\n        var _flash = _c._$getFlashProxy('http://nei.netease.com');\n        equal(_flash,'http://nei.netease.com/proxy/crossdomain.xml','http://nei.netease.com/proxy/crossdomain.xml');\n        equal(_c._$get('portrait'),'/res/portrait/','NEJ各文件配置portrait');\n        equal(_c._$get('ajax.swf'),'/res/nej_proxy_flash.swf','NEJ各文件配置ajax');\n        equal(_c._$get('chart.swf'),'/res/nej_flex_chart.swf','NEJ各文件配置chart');\n        equal(_c._$get('audio.swf'),'/res/nej_player_audio.swf','NEJ各文件配置audio');\n        equal(_c._$get('video.swf '),undefined,'NEJ各文件配置video');\n        equal(_c._$get('clipboard.swf'),'/res/nej_clipboard.swf','NEJ各文件配置clipboard');\n        equal(_c._$get('upload.image.swf'),'/res/nej_upload_image.swf','NEJ各文件配置upload');\n        if (_p._$KERNEL.browser == 'ie' && _p._$KERNEL.release <= 3.0){\n            equal(_c._$get('storage.swf'),'/res/nej_storage.swf','NEJ各文件配置storage');\n         }else{\n            ok(true,'高版本不需要 storage');\n         }\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}config.test.js',\n    ['{lib}base/config.js'],f);\n});\n"
  },
  {
    "path": "src/base/test/constant.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>constant测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit constant test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n \t\t<script src=\"../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./constant.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/base/test/constant.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"constant\");\n    var _p = NEJ.P('nej.g'),\n        _g = NEJ.P('nej.p');\n\n    //开始单元测试\n    test('测试静态变量', function() {\n        equal(typeof(_p._$CODE_NOTASGN),'number','需要指定的参数未指定');\n        equal(typeof(_p._$CODE_NOTSPOT),'number','不支持操作');\n        equal(typeof(_p._$CODE_TIMEOUT),'number','操作超时');\n        equal(typeof(_p._$CODE_ERREVAL),'number','字符串作为脚本执行异常');\n        equal(typeof(_p._$CODE_ERRCABK),'number','回调执行异常');\n        equal(typeof(_p._$CODE_ERRSERV),'number','服务器返回异常');\n        equal(typeof(_p._$CODE_ERRABRT),'number','异常终止的错误码');\n        equal(_p._$HEAD_CT,'Content-Type','请求头content-type统一名称');\n        equal(_p._$HEAD_CT_PLAN,'text/plain','文本请求头content-type值');\n        equal(_p._$HEAD_CT_FILE,'multipart/form-data','文件请求头content-type值');\n        equal(_p._$HEAD_CT_FORM,'application/x-www-form-urlencoded','表单请求头content-type值');\n        if (_g._$KERNEL.browser == 'ie' && _g._$KERNEL.release<=3.0){\n            equal(_p._$BLANK_IMAGE,'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==','空图片BASE64编码地址');\n        }else{\n            equal(_p._$BLANK_IMAGE,'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==','空图片BASE64编码地址');\n        }\n\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}constant.test.js',\n    ['{lib}base/constant.js'],f);\n});\n"
  },
  {
    "path": "src/base/test/element.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>element测试页面</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style id='style-id' type=\"text/css\">\n\t\t\t#js-node{position: relative;}\n\t\t\t#bottom{margin:1200px 0 0 2200px;}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">nej element.js test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<div class=\"node\" id=\"js-node\">\n\t\t\t<span>node</span>\n\t\t\t<span class='node2'>node2</span>\n\t\t</div>\n\t\t<div id=\"ele\" style=\"position:relative;padding:5px 0 0 10px;\">\n\t\t\t<div id=\"ele2\">123</div>\n\t\t</div>\n\t\t<textarea id=\"cursor-area\">请选中我,3秒后测试开始</textarea>\n\t\t<div id='css3d' class='css3d'>\n\t\t\t设置css3d属性\n\t\t</div>\n\t\t<div id='ul'><ul>ul</ul><p>p</p><h1>h1</h1></div>\n\t\t<div id='frameCnt'>\n\t\t</div>\n\t\t<div id='bottom'>\n\t\tbottom\n\t\t</div>\n\t\t<div id=\"full-div\">full-div</div>\n\t\t<script src=\"../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./element.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/base/test/element.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module('element');\n    var p = NEJ.P('nej.p');\n    var e = NEJ.P('nej.e');\n    var v = NEJ.P('nej.v');\n\n    //开始单元测试\n    test('判断平台',function(){\n        equal(typeof(p._$KERNEL),'object','浏览器是'+p._$KERNEL.browser+'----前缀是'+p._$KERNEL.prefix.css+'----scc3d='+p._$SUPPORT.css3d);\n    });\n\n    test('xml2object',function(){\n        var _xml = '<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\\\n        <netease>\\\n          <albums>\\\n              <p><id><code><id>id</id>\\\n                  <code>code</code>\\\n                  <name>name</name>\\</code></id></p>\\\n              <album>\\\n                  <id>id</id>\\\n                  <code>code</code>\\\n                  <name>name</name>\\\n              </album>\\\n          </albums>\\\n        </netease>';\n        var _xml2 = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\\n<netease>\\\n<albums>\\\n    <code>1</code>\\\n    <album>\\\n        <id>198114001</id>\\\n        <name></name>\\\n        <desc></desc>\\\n        <auth>2</auth>\\\n        <privacy>2</privacy>\\\n        <count>110</count>\\\n        <tcover>4/zxeW5iOfq3ppXe1etviJwg==/611645124409898904.jpg</tcover>\\\n        <coverurl>1/_0CvRVkR39uuLIIEHVSAJQ==/1278740819214249961.jpg</coverurl>\\\n        <coverurl160>5/eoc7HI1101yikVJnzbBADg==/3082713944952843165.jpg</coverurl160>\\\n    </album>\\\n</albums>\\\n</netease>';\n        equal(e._$xml2object(_xml2).netease.albums.album.auth,'2','XML转对象');\n    });\n\n    QUnit.test('textarea光标测试',function(){\n        QUnit.stop();\n        var _cursor = e._$get('cursor-area');\n        setTimeout(function(){\n            equal(e._$cursor(_cursor),{start:100,end:2000},'请人工检查光标起始位置和结束位置');\n            QUnit.start();\n        },2000);\n    });\n\n    QUnit.test('fullScreen测试',function(){\n        QUnit.stop();\n        var _cursor = e._$get('full-div');\n        setTimeout(function(){\n            e._$fullScreen(_cursor);\n            equal(_cursor.style.width,document.body.offsetWidth + 'px','节点占全屏');\n            QUnit.start();\n        },3000);\n    });\n\n    test('element',function(){\n        var _node = document.getElementById('js-node');\n        e._$setStyle(_node,'z-index',888);\n        equal(e._$getStyle(_node,'z-index'),888,'设置z-index样式');\n        equal(e._$get('js-node'),_node,'取节点对象，通过ID');\n        equal(e._$get(_node),_node,'取节点对象，通过对象');\n        //需要重复测试\n        equal(typeof(e._$id(_node)),'string','为节点设置一个唯一的ID');//返回本身id，没有id生成一个auto-id-xxxxxxxx\n        /**\n         * <div class=\"node\" id=\"js-node\">\n         *     <span>node</span>\n         *     <span>node2</span>\n         * </div>\n         */\n        equal(e._$getSibling('ele').id,'cursor-area','根据从兄弟节点中搜索符合条件的节点')\n        equal(e._$getChildren(_node)[0].innerHTML,'node','取节点的子节点列表');\n        equal(e._$getChildren(_node,'node2')[0].innerHTML,'node2','根据样式标识取子节点列表');\n        equal(e._$getByClassName(document,'node')[0],_node,'根据类名取节点列表');\n        /**\n         * 创建<div id='js-div'></div>节点\n         * 追加到document.body下\n         */\n        equal(e._$create('div','js-div',document.body),e._$getByClassName(document,'js-div')[0],'创建一个节点');\n        //xFrame\n        stop();\n        var _xFrame = e._$createXFrame({\n            src:'http://www.baidu.com',\n             name:'百度',\n            parent:'frameCnt',\n            visible:false,\n            onload:function(){\n                ok(true,'框架载入成功');\n                equal(_xFrame.name,'百度','name设置');\n                equal(_xFrame.style.display,'none','visible设置');\n                start();\n            }\n        });\n        var _id = e._$id(e._$getByClassName(document,'js-div')[0]);\n        var _ele = e._$get(_id);\n        //css3D\n        var _css3d = e._$get('css3d');\n        e._$css3d(_css3d,'translate',{x:'100px',y:'20px',z:'30px'});\n        equal(_css3d.style['-webkit-transform'],'translate3d(100px, 20px, 30px)','设置translate3d属性,仅safari和chrome支持');\n        e._$css3d(_css3d,'translate',{x:'100px',y:'20px',z:'40px'});\n        equal(_css3d.style['-webkit-transform'],'translate3d(100px, 20px, 40px)','重新设置translate3d属性,仅safari和chrome支持');\n        e._$css3d(_css3d,'scale',{x:1,y:2,z:2});\n        equal(_css3d.style['-webkit-transform'],'scale3d(1, 2, 2)','设置scale3d属性,仅safari和chrome支持');\n        e._$css3d(_css3d,'scale',{x:2,y:3,z:3});\n        equal(_css3d.style['-webkit-transform'],'scale3d(2, 3, 3)','重新设置scale3d属性,仅safari和chrome支持');\n        e._$css3d(_css3d,'rotate',{x:1,y:2,z:2,a:'45deg'});\n        equal(_css3d.style['-webkit-transform'],'rotate3d(1, 2, 2, 45deg)','设置rotate3d属性,仅safari和chrome支持');\n        e._$css3d(_css3d,'rotate',{x:2,y:1,z:1,a:'-75deg'});\n        equal(_css3d.style['-webkit-transform'],'rotate3d(2, 1, 1, -75deg)','重新设置rotate3d属性,仅safari和chrome支持');\n        e._$style(_css3d,{color:'red',background:'black'});\n        equal(_css3d.style['color'],'red','通过_$style设置样式');\n        equal(e._$getStyle(_css3d,'color'),'rgb(255, 0, 0)','去节点的color样式');\n        /**\n         * |a:1,b:0,c:0,d:1,e:0:f:0|\n         * |m11:1,m12:0,m13:0,m14:0|\n         * |m21:0,m22:1,m23:0,m24:0|\n         * |m31:0,m32:0,m33:1,m34:0|\n         * |m41:0,m42:0,m43:0,m44:1|\n         */\n        var _matrix = e._$matrix(\"matrix(1,0,0,1,0,0)\");\n        //移除节点\n        e._$remove(_ele,true);\n        equal(e._$get(_id),null,'删除节点，是否在删除节点前移除事件，要测试v._$clearEvent(_element)接口');\n        var _ele = e._$create('div','js-div',document.body);\n\t\t_ele.innerText = 'hello';\n        e._$removeByEC(_ele);\n/* */    equal(e._$getByClassName(document,'js-div').length,0,'节点移除到内存中');\n        var _ele = e._$create('div','js-div',document.body);\n        //设置data\n        var _a = e._$dataset(_ele,'img','就是一个值');\n        equal(_a,'就是一个值','给对象设置属性值');\n        /** _$dom2xml&&_$xml2dom\n            var _d2m = e._$dom2xml(_css3d);\n            var _m2d = e._$xml2dom(_d2m);\n            equal(_css3d,_m2d,'dom转xml，xml转dom，转后结果一致');\n            var _d2m = e._$dom2xml(_css3d);\n            var _t2t = e._$text2type(_d2m,\"xml\");\n            equal(_css3d,_css3d,'dom转xml字符串，再转成dom节点');\n        */\n        var _text = '<div id=\"abc\">xxxx</div>';\n        var _t2t = e._$text2type(_text,\"xml\");\n        equal(typeof(_t2t),'object','text2type');\n        var _text = '{\"a\":\"b\"}';\n        var _t2t = e._$text2type(_text,\"json\");\n        propEqual(_t2t,{\"a\":\"b\"},'text2type');\n        //_$html2node\n        var _ele = e._$html2node('<div id=\"testnode\"><img src=\"\" /></div>');\n        equal(_ele.id,'testnode','html代码转节点对象');\n        var _ele = e._$html2node('<div id=\"testnode\"></div><div id=\"testnode1\"></div><div id=\"testnode2\"></div>');\n        equal(e._$getChildren(_ele).length,3,'html代码转节点对象');\n        //_$pushCSSText\n        e._$pushCSSText('.css3d{width:300px;}');\n        equal(_css3d.style.width,'','未激活样式');\n        e._$dumpCSSText();\n        equal(_css3d.offsetWidth,300,'激活样式');\n        //_$getPageBox\n        var _pb = e._$getPageBox();\n        equal(typeof(_pb.scrollTop),'number','取盒子的信息');\n        equal(typeof(_pb.scrollLeft),'number','取盒子的信息');\n        equal(typeof(_pb.clientWidth),'number','取盒子的信息');\n        equal(typeof(_pb.clientHeight),'number','取盒子的信息');\n        equal(typeof(_pb.scrollWidth),'number','取盒子的信息');\n        equal(typeof(_pb.scrollHeight),'number','取盒子的信息');\n        notEqual(_pb.scrollTop,NaN,'取盒子的信息');\n        notEqual(_pb.scrollLeft,NaN,'取盒子的信息');\n        notEqual(_pb.clientWidth,NaN,'取盒子的信息');\n        notEqual(_pb.clientHeight,NaN,'取盒子的信息');\n        notEqual(_pb.scrollWidth,NaN,'取盒子的信息');\n        notEqual(_pb.scrollHeight,NaN,'取盒子的信息');\n\n        var _limit = {width:100,height:10};\n        var _box = e._$getMaxBox({width:250,height:10},_limit);\n        propEqual(_box,{width:100,height:4},'给定大小缩放至限制区域内');\n        var _box = e._$getMaxBox({width:100,height:50},_limit);\n        propEqual(_box,{width:20,height:10},'给定大小缩放至限制区域内');\n        var _bottom = e._$get('bottom');\n        e._$scrollTo(_bottom);\n        notEqual(e._$getPageBox().scrollTop,0,'scrollTo指定节点');\n        notEqual(e._$getPageBox().scrollLeft,0,'scrollTo指定节点');\n        var _align = e._$align({width:200,height:200},{width:100,height:100});\n        propEqual(_align,{top:50,left:50},'获取滚动视窗');\n        var _align = e._$align({width:200,height:200},{width:100,height:100},'left bottom');\n        propEqual(_align,{top:100,left:0},'获取滚动视窗');\n        /**_$query\n        var _qdom = e._$query('.css3d',document);\n        equal(_qdom[0],_css3d,'通过选择器取节点');\n        */\n        var _bd = e._$getScrollViewPort(_node);\n        equal(typeof(_bd),'object','获取滚动视窗');\n        //equal(_bd,document.documentElement,'获取滚动视窗');\n        //_$offset,没有to参数就计算到根节点\n        equal(typeof(e._$offset(_node).x),'number','计算两个节点之间的偏移量');\n        equal(typeof(e._$offset(_node).y),'number','计算两个节点之间的偏移量');\n        notEqual(typeof(e._$offset(_node).x),NaN,'计算两个节点之间的偏移量');\n        notEqual(typeof(e._$offset(_node).y),NaN,'计算两个节点之间的偏移量');\n        var _result = e._$offset(e._$get('ele2'),e._$get('ele'));\n        equal(_result.x,10,\"计算两个节点之间的偏移量，指定了2个节点\");\n        e._$setStyle(_node,'color','#f00');\n        equal(e._$getStyle(_node,'color'),'rgb(255, 0, 0)','设置color样式');\n        e._$setStyle(_node,'color2','red2');\n        equal(_node.style.color2,'red2','非标准属性一样设置成功，但是节点上没有显示，设置样式');\n        equal(e._$getStyle(_node,'color'),'rgb(255, 0, 0)','取样式值');\n        notEqual(e._$getStyle(_node,'color'),'red','样式值跟存的不一样,取的时候按照标准属性');\n        equal(e._$getStyle(_node,'color2'),'','非标准属性返回空字符串');\n        e._$addStyle('body{font-size:20px}');\n        equal(e._$getStyle(_node,'fontSize'),'20px','添加样式');\n        e._$addScript('document.getElementById(\"js-node\").style.color = \"green\"');\n        equal(e._$getStyle(_node,'color'),'rgb(0, 128, 0)','脚本添加颜色');\n        e._$addClassName(_node,'fc01 fc03');\n        equal(_node.className,'node fc01 fc03','新增样式类，多个样式用空格分开');\n        e._$delClassName(_node,'node');\n        equal(_node.className,'fc01 fc03','删除样式类，多个样式用空格分开');\n        e._$replaceClassName(_node,'fc01 fc03','node');\n        equal(_node.className,'node','替换节点的样式类名称，多个样式用空格分隔');\n        e._$addClassName(_node,'node');\n        equal(e._$hasClassName(_node,'node'),true,'检测节点是否包含指定样式，多个样式用空格分隔，检测时包含其中之一即表示包含');\n        equal(typeof(e._$appendCSSText('style-id','#bottom{color:red;}')),'object','appendCSSText');\n    });\n\n    QUnit.test('clearChildren',function(){\n        var _ul = e._$get('ul');\n        e._$clearChildren(_ul);\n        equal(e._$getChildren(_ul).length,0,'子节点被清空了');\n    });\n\n    QUnit.test('wrapInline',function(){\n        var _ul = e._$get('js-node');\n        // equal(e._$wrapInline(_ul),0,'wrapInline-default');\n        equal(e._$wrapInline(_ul,{tag:'label',clazz:'label-class'}),0,'wrapInline-p');\n    });\n\n    QUnit.test('attr',function(){\n        var _src = e._$attr('js-node','data-img','xxx');\n        equal(_src,'xxx','attr');\n    })\n\n    QUnit.test('mask and unmask',function(){\n        ok('没有做测试')\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}element.test.js',\n    ['{lib}base/element.js','{lib}util/encode/json.js'],f);\n});"
  },
  {
    "path": "src/base/test/event.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>event.js测试页面</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style type=\"text/css\">\n\t\t\t.node{width:100px;height:50px;-webkit-transition:3s;-moz-transition:3s;}\n\t\t\t.box{width:950px;height:950px;background:green;}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">nej event.js test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<div class=\"node\" id=\"js-node\">\n\t\t\t<span>点击我</span>\n\t\t</div>\n\t\t<div id='js-box' class='box'>touch测试</div>\n\t\t<input id='js-input' type='text' />\n\t\t<textarea id='js-textarea'></textarea>\n\t\t<iframe id='js-iframe'></iframe>\n\t\t<script src=\"../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./event.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/base/test/event.test.js",
    "content": "var f = function(){\n\t//定义测试模块\n\tmodule('event');\n\tvar p = NEJ.P('nej.p');\n\tvar e = NEJ.P('nej.e');\n\tvar v = NEJ.P('nej.v');\n\tvar func = function(_eventType,_node){\n\t\t_node = _node || e._$get('js-node');\n\t\tvar _num = 0,_ele,_ele2,_pageX,_pageY;\n\t\tvar _dispatch = function(_node){\n\t\t\tv._$dispatchEvent(_node,_eventType);\n\t\t}\n\t\tvar _f = function(e){\n\t\t\t_num = 10;\n\t\t\t_ele = v._$getElement(e);\n\t\t\t//带过滤器\n\t\t\t_ele2 = v._$getElement(e,function(_element){\n\t\t\t\treturn _element.id != 'js-node';\n\t\t\t});\n\t\t};\n\t\tv._$addEvent(_node,_eventType,_f);\n\t\t_dispatch(_node);\n\t\tequal(_ele.id,'js-node','获取触发事件的节点');\n\t\tnotEqual(_ele2.id,'js-node','获取触发事件的节点,过滤接口是id不能为js-node');\n\t\tequal(_num,10,'事件添加成功，并且触发了');\n\t\t_num = 0;\n\t\tv._$delEvent(_node,_eventType,_f);\n\t\t_dispatch(_node);\n\t\tequal(_num,0,'事件已经被删除了，所以值不变');\n\t\tv._$addEvent(_node,_eventType,_f);\n\t\tv._$clearEvent(_node,_eventType);\n\t\tv._$clearEvent(_node);\n\t\t_dispatch(_node);\n\t\tequal(_num,0,'所有事件已经被清理了，所以值不变');\n\t\tv._$addEvent(_node,_eventType,_f);\n\t\tv._$clearEvent(_node,'xxx');\n\t\t_dispatch(_node);\n\t\tnotEqual(_num,0,'清理的类型不对，所以值变了');\n\t\tv._$clearEvent(_node);\n\t\tv._$addEvent(_node,_eventType,_f);\n\t\tv._$clearEvent(_node,'function');\n\t\t_dispatch(_node);\n\t\tnotEqual(_num,0,'清理的类型用关键字试试');\n\t\tv._$clearEvent(_node);\n\t\t_num = 0;\n\t\tv._$addEvent(_node,_eventType,_f);\n\t\t_dispatch(_node.children[0]);\n\t\tequal(_num,10,'事件冒泡了');\n\t\tv._$clearEvent(_node);\n\t\t_num = 0;\n\t\tvar _f = function(e){\n\t\t\tv._$stop(e);\n\t\t\t_num = 10;\n\t\t\t_ele = v._$getElement(e);\n\t\t\t_ele2 = v._$getElement(e,function(_element){\n\t\t\t\treturn _element.id != 'js-node';\n\t\t\t});\n\t\t};\n\t\tvar _f2 = function(e){\n\t\t\tv._$stop(e);\n\t\t\tif(e.type == _eventType){\n\t\t\t\t_pageX = v._$pageX(e);\n\t\t\t\t_pageY = v._$pageY(e);\n\t\t\t\tequal(_pageX,NaN,'结果是事件触发的pageX');\n\t\t\t\tequal(_pageY,NaN,'结果是事件触发的pageY');\n\t\t\t}\n\t\t\t_num = 20;\n\t\t\t_ele = v._$getElement(e);\n\t\t\t_ele2 = v._$getElement(e,function(_element){\n\t\t\t\treturn _element.id != 'js-node';\n\t\t\t});\n\t\t};\n\t\tv._$addEvent(_node,_eventType,_f);\n\t\tv._$addEvent(_node.children[0],_eventType,_f2);\n\t\t_dispatch(_node.children[0]);\n\t\tequal(_num,20,'阻止掉事件冒泡');\n\t\t_num = 0;\n\t\tv._$clearEvent(_node);\n\t\tv._$clearEvent(_node.children[0]);\n\t\tv._$addEvent(_node,_eventType,_f,true);\n\t\t//是否捕获阶段 IE没有\n\t\tv._$addEvent(_node.children[0],_eventType,_f2,true);\n\t\t_dispatch(_node.children[0]);\n\t\tequal(_num,10,'阻止掉事件捕获');\n\t};\n\t// 开始单元测试\n\n\n\ttest('event mouseover',function(){\n\t\tvar _eventType = 'mouseover';\n\t\tfunc(_eventType);\n\t});\n\n\ttest('event click',function(){\n\t\tvar _eventType = 'click';\n\t\tfunc(_eventType);\n\t});\n\n\ttest('event change',function(){\n\t\tvar _eventType = 'change';\n\t\tfunc(_eventType,e._$get('js-input'));\n\t});\n\n\tmodule('event常规测试');\n\n\ttest('null',function(){\n\t\texpect(0);\n\t\tvar _node = e._$get('js-node');\n\t\tvar _f = function(){};\n\t\tv._$addEvent(_node,'click',_f);\n\t\tv._$delEvent(null,'click',_f);\n\t});\n\n\ttest('input event',function(){\n\t\tstop();\n\t\tvar _input = e._$get('js-input');\n\t\tv._$addEvent(_input,'input',function(_event){\n\t\t\tok(true,'input text 成功触发input 事件');\n\t\t\tstart();\n\t\t});\n\t\tv._$dispatchEvent(_input,'input');\n\t});\n\n\ttest('textarea event',function(){\n\t\tstop();\n\t\tvar _textarea = e._$get('js-textarea');\n\t\tv._$addEvent(_textarea,'input',function(_event){\n\t\t\tok(true,'textarea 成功触发input 事件');\n\t\t\tstart();\n\t\t});\n\t\tv._$dispatchEvent(_textarea,'input');\n\t});\n\n\ttest('load event',function(){\n\t\tstop();\n\t\tvar _iframe = e._$get('js-iframe');\n\t\tv._$addEvent(_iframe,'load',function(_event){\n\t\t\tok(true,'ifram load事件成功触发');\n\t\t\tstart();\n\t\t});\n\t\t_iframe.src = 'http://www.baidu.com';\n\t});\n\n\tif (p._$support('css3d')){\n\t\ttest('transitionend event',function(){\n\t\t\tstop();\n\t\t\tvar _node = e._$get('js-node');\n\t\t\te._$setStyle(_node,'transition-duration','1s');\n\t\t\tv._$addEvent(_node,'transitionend',function(_event){\n\t\t\t\tok(true,'transitionend 事件成功触发');\n\t\t\t\tstart();\n\t\t\t});\n\t\t\te._$css3d(_node,'rotate',{x:2,y:1,z:0,a:'105deg'});\n\t\t});\n\t}\n\n\tmodule('user helper test');\n\ttest(\"检测事件触发点\", function(){\n\t\tstop();\n\t\tvar _pageX,_pageY;\n\t\tvar _f2 = function(_e){\n\t\t\tif(_e.type == 'click'){\n\t\t\t\t_pageX = v._$pageX(_e);\n\t\t\t\t_pageY = v._$pageY(_e);\n\t\t\t\tequal(typeof(_pageX),'number','检测事件触发点pageX'+_pageX);\n\t\t\t\tequal(typeof(_pageY),'number','检测事件触发点pageY'+_pageY);\n\t\t\t\tstart();\n\t\t\t}\n\t\t};\n\t\tvar _node = e._$get('js-node');\n\t\tv._$addEvent(_node,'click',_f2);\n\t\tv._$dispatchEvent(_node,'click');\n\t});\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n\tdefine('{pro}event.test.js',\n    ['{lib}base/event.js','{lib}base/element.js'],f);\n});"
  },
  {
    "path": "src/base/test/global.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>global测试页面</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">nej global.js test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n \t\t<script src=\"../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./global.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/base/test/global.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module('global');\n\n    //开始单元测试\n    test('Function prototype',function(){\n        equal(typeof(Function.prototype._$bind),'function','函数对象加入了_$bind方法');\n        equal(typeof(Function.prototype._$bind2),'function','函数对象加入了_$bind2方法');\n    });\n\n    test('window.MWF', function() {\n        deepEqual(NEJ.O,{},'只读空对象实例');\n        deepEqual(NEJ.R,[],'只读空数组实例');\n        notEqual(NEJ.F,function(){return !1;},'空函数实例每个都不equal');\n        notDeepEqual(NEJ.F,function(){return !1;},'空函数实例每个都不DeepEqual');\n    });\n\t// test('NEJ.X after window.MWF',function(){\n //            var _obj ={},_obj2 = {};\n //            _obj.num = 2;\n //            NEJ.X(_obj2,_obj,function(_num){\n //                if(_num == 3)\n //                    return false;\n //            });\n //            equal(_obj.num,_obj2.num,'拷贝对象属性');\n //            var _obj = {},_obj2 = {};\n //            _obj.num1 = 3;\n //            _obj.num2 = 4;\n //            NEJ.X(_obj2,_obj,function(_num){\n //                if(_num == 3)\n //                    return true;\n //            });\n //            notEqual(_obj.num1,_obj2.num1,'拷贝对象通过过滤接口属性');\n //            equal(_obj.num2,_obj2.num2,'拷贝对象通过过滤接口属性');\n //        });\n //    test('NEJ.EX after window.MWF',function(){\n //        /**\n //         * 以下代码从_obj2取_obj中对应的属性值\n //         * 拷贝结束后_obj->{num:1,num1:aa}\n //         */\n //        var _obj ={},_obj2 = {};\n //        _obj.num = 1;\n //        _obj.num1 = 'aa';\n //        _obj2.num = 2;\n //        NEJ.EX(_obj,_obj2);\n //        equal(_obj.num,_obj2.num,'拷贝对象属性');\n //        var _obj = {},_obj2 = {};\n //        _obj.num = '3';\n //        _obj2.num = '4';\n //        NEJ.EX(_obj,_obj2);\n //        equal(_obj.num,_obj2.num,'拷贝对象通过过滤接口属性');\n //        _obj.num = 'aaa';\n //        _obj2.num = 'null';\n //        NEJ.EX(_obj,_obj2);\n //        equal(_obj.num,_obj2.num,'拷贝对象通过过滤接口属性,测试字符串null');\n //        _obj.num = 'aaa';\n //        _obj2.num = null;\n //        NEJ.EX(_obj,_obj2);\n //        notEqual(_obj.num,_obj2.num,'拷贝对象通过过滤接口属性,测试null');\n //        _obj.num = 'aaa';\n //        _obj2.num = undefined;\n //        NEJ.EX(_obj,_obj2);\n //        notEqual(_obj.num,_obj2.num,'拷贝对象通过过滤接口属性,测试undefined');\n //        _obj.num = 'aaa';\n //        _obj2.num = 'undefined';\n //        NEJ.EX(_obj,_obj2);\n //        equal(_obj.num,_obj2.num,'拷贝对象通过过滤接口属性,测试字符串undefined');\n //        _obj.num = 'aaa';\n //        _obj2.num = Number.NaN;\n //        NEJ.EX(_obj,_obj2);\n //        notEqual(_obj.num,_obj2.num,'拷贝对象通过过滤接口属性,测试Number.NaN值');\n //        _obj.num = 'aaa';\n //        _obj2.num = Number.MAX_VALUE;\n //        NEJ.EX(_obj,_obj2);\n //        equal(_obj.num,_obj2.num,'拷贝对象通过过滤接口属性,测试Number.MAX_VALUE值');\n //        _obj.num = 'aaa';\n //        _obj2.num = Number.MIN_VALUE;\n //        NEJ.EX(_obj,_obj2);\n //        equal(_obj.num,_obj2.num,'拷贝对象通过过滤接口属性,测试Number.MIN_VALUE');\n //    });\n\n    test('NEJ.P',function(){\n        equal(NEJ.P('a.b.c'),a.b.c,'字符串a.b.c生成命名空间');\n        equal(NEJ.P('window.a.b.c'),window.a.b.c,'字符串window.a.b.c生成命名空间');\n        deepEqual(NEJ.P('0.2.3'),{},'字符串0.2.3不能生成正确命名空间');\n        deepEqual(NEJ.P('function.for'),{},'关键字不能生成正确命名空间');\n    });\n\n    // test('NEJ.C',function(){\n    //     var _f = NEJ.C();\n    //     var _num = 0;\n    //     _f.__static = function(){\n    //         return 'static';\n    //     };\n    //     _f.prototype.__init = function(){\n    //         _num  = 10;\n    //     };\n    //     var _f2 = NEJ.C();\n    //     //_fn2==_f2.prototype\n    //     var _fn2 = _f2._$extend(_f);\n    //     _fn2.__init = function(){\n    //         this.__super();\n    //         _num--;\n    //     }\n    //     var _xf = new _f();\n    //     equal(typeof(_f),'function','返回一个函数对象');\n    //     equal(typeof(_f._$bind),'function','返回的对象有_$bind方法,继承自Function');\n    //     equal(typeof(_f._$bind2),'function','返回的对象有_$bind2方法,继承自Function');\n    //     var _x2f = new _f2();\n    //     equal(_num,9,'父类__init后，子类__init会被调用');\n    //     equal(_f2.__static(),'static','默认继承了静态方法，如不继承传入false参数');\n    // });\n\n    // test('_$bind接口',function(){\n    //     var _f = NEJ.C();\n    //     _f.prototype.__init = function(){\n\n    //     };\n    //     var _f2 = NEJ.C();\n    //     var _obj = {num:3};\n    //     var _fn2 = _f2._$extend(_f);\n    //     _fn2.__print = function(_obj,_obj2){\n    //         return arguments[0]+arguments[1];\n    //     };\n    //     _fn2.__init = function(){\n    //         this.__super();\n    //         this.num = 33;\n    //         var _fun = this.__print._$bind(this,'obj');\n    //         var _fun2 = this.__print._$bind2(this,'obj');\n    //         equal(_fun('aaa'),'objaaa','测试_$bind方法,参数的顺序调用');\n    //         equal(_fun2('bbb'),'bbbobj','测试_$bind2方法,参数的倒序调用');\n    //     };\n    //     var _f22 = new _f2();\n    // });\n\n    test('trim接口',function(){\n        equal('  dfdf @$#%^  dfdf  '.trim(),'dfdf @$#%^  dfdf','测试trim接口前后去空格');\n        equal('  function  '.trim(),'function','关键字');\n        equal('  function(){return 0;}  '.trim(),'function(){return 0;}','函数');\n        equal('  \\\\\\*function()\\*\\\\{return 0;}  '.trim(),'\\\\\\*function()\\*\\\\{return 0;}','转义字符');\n        equal('  &lt;  '.trim(),'&lt;','转义字符');\n    });\n\n    test('aop增强接口',function(){\n        var _obj = {a:0};\n        var _f = function(){\n            _obj.a = 1;\n            return 'aop增强操作1';\n        };\n        var _f2 = function(_event){\n            _obj.a = 2;\n            _event.value = 'aop增强操作2';\n        };\n        var _f3 = function(_event){\n            _obj.a = 3;\n            _event.value = 'aop增强操作3';\n        }\n        var _f = _f._$aop(_f2,_f3);\n        var _value = _f();\n        equal(_obj.a,3,'aop增强操作');\n        equal(_value,'aop增强操作3','aop增强操作返回值是某个增强操作的返回值');\n    });\n\n    test('aop增强接口,stopped',function(){\n        var _obj = {a:0};\n        var _f = function(){\n            _obj.a = 1;\n            return 'aop增强操作';\n        };\n        var _f2 = function(_event){\n            _event.stopped = true;\n            _obj.a = 2;\n            _event.value = 'aop增强操作2';\n        };\n        var _f3 = function(_event){\n            _obj.a = 3;\n            _event.value = 'aop增强操作3';\n        }\n        var _f = _f._$aop(_f2,_f3);\n        _f();\n        equal(_obj.a,2,'aop增强操作');\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}global.test.js',['{lib}base/global.js'],f);\n});\n\n"
  },
  {
    "path": "src/base/test/klass.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>klass测试页面</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">nej klass.js test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n \t\t<script src=\"../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./klass.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/base/test/klass.test.js",
    "content": "var f = function(_k){\n    //定义测试模块\n    module('global');\n\n    //开始单元测试\n    test('NEJ.C',function(){\n        var _f = _k._$klass();\n        var _num = 0;\n        _f.__static = function(){\n            return 'static';\n        };\n        _f.prototype.__init = function(){\n            _num  = 10;\n        };\n        var _f2 = _k._$klass();\n        //_fn2==_f2.prototype\n        var _fn2 = _f2._$extend(_f);\n        _fn2.__init = function(){\n            this.__super();\n            _num--;\n        }\n        var _xf = new _f();\n        equal(typeof(_f),'function','返回一个函数对象');\n        equal(typeof(_f._$bind),'function','返回的对象有_$bind方法,继承自Function');\n        equal(typeof(_f._$bind2),'function','返回的对象有_$bind2方法,继承自Function');\n        var _x2f = new _f2();\n        equal(_num,9,'父类__init后，子类__init会被调用');\n        equal(_f2.__static(),'static','默认继承了静态方法，如不继承传入false参数');\n    });\n\n    test('_$bind接口',function(){\n        var _f = _k._$klass();\n        _f.prototype.__init = function(){\n\n        };\n        var _f2 = _k._$klass();\n        var _obj = {num:3};\n        var _fn2 = _f2._$extend(_f);\n        _fn2.__print = function(_obj,_obj2){\n            return arguments[0]+arguments[1];\n        };\n        _fn2.__init = function(){\n            this.__super();\n            this.num = 33;\n            var _fun = this.__print._$bind(this,'obj');\n            var _fun2 = this.__print._$bind2(this,'obj');\n            equal(_fun('aaa'),'objaaa','测试_$bind方法,参数的顺序调用');\n            equal(_fun2('bbb'),'bbbobj','测试_$bind2方法,参数的倒序调用');\n        };\n        var _f22 = new _f2();\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}global.test.js',['{lib}base/klass.js'],f);\n});\n\n"
  },
  {
    "path": "src/base/test/platform.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>platform测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit platform test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n \t\t<script src=\"../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./platform.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/base/test/platform.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"platform\");\n    var _p = NEJ.P('nej.p');\n\n    //开始单元测试\n    test('NEJ配置文件测试', function() {\n    \tvar _isWindows = _p._$is('desktop');\n        equal(_isWindows,true,'判断是否指定平台');\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}platform.test.js',\n    ['{lib}base/platform.js'],f);\n});\n"
  },
  {
    "path": "src/base/test/util.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>util测试页面</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">nej util.js test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<div id=\"js-node\">node</div>\n\t\t<script src=\"../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./util.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/base/test/util.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module('util');\n    var _util = NEJ.P('nej.u');\n    //开始单元测试\n    test('util',function(){\n        //判断\n        equal(_util._$isFunction(function(){}),true,'判断函数类型');\n        equal(_util._$isFunction(),false,'判断函数类型');\n        equal(_util._$isFunction(null),false,'判断函数类型');\n        equal(_util._$isString('abc'),true,'判断字符串类型');\n        equal(_util._$isString(),false,'判断字符串类型');\n        equal(_util._$isString(null),false,'判断字符串类型');\n        equal(_util._$isNumber(\"123\"),false,'判断数字类型');\n        equal(_util._$isNumber(),false,'判断数字类型');\n        equal(_util._$isNumber(null),false,'判断数字类型');\n        equal(_util._$isNumber(0),true,'判断数字类型');\n        equal(_util._$isNumber(-0),true,'判断数字类型');\n        equal(_util._$isNumber(+0),true,'判断数字类型');\n        equal(_util._$isNumber(-1),true,'判断数字类型');\n        equal(_util._$isNumber(NaN),true,'判断数字类型');\n        equal(_util._$isNumber(Number.NEGATIVE_INFINITY),true,'判断数字类型');\n        equal(_util._$isNumber(Number.MAX_VALUE),true,'判断数字类型');\n        equal(_util._$isNumber(Number.MIN_VALUE),true,'判断数字类型');\n        equal(_util._$isBoolean(0),false,'判断布尔类型');\n        equal(_util._$isBoolean(),false,'判断布尔类型');\n        equal(_util._$isBoolean(null),false,'判断布尔类型');\n        equal(_util._$isBoolean(false),true,'判断布尔类型');\n        equal(_util._$isBoolean(true),true,'判断布尔类型');\n        equal(_util._$isDate(),false,'判断date类型');\n        equal(_util._$isDate(null),false,'判断date类型');\n        equal(_util._$isDate(new Date()),true,'判断date类型');\n        equal(_util._$isArray(),false,'判断Array类型');\n        equal(_util._$isArray(null),false,'判断Array类型');\n        equal(_util._$isArray([1,'a',{a:1}]),true,'判断Array类型');\n        equal(_util._$isObject(function(){}),false,'判断Object类型');\n        equal(_util._$isObject(),false,'判断Object类型');\n        equal(_util._$isObject(null),false,'判断Object类型');\n        equal(_util._$isObject({}),true,'判断Object类型');\n        equal(_util._$isObject({a:1}),true,'判断Object类型');\n\n        //功能\n        var _node = document.getElementById('js-node');\n        equal(_util._$indexOf([1,2,3],3),2,'查找列表中的某一项');\n        //常用来编码html结构,比如:<div> - > &lt;div&gt;\n        equal(_util._$encode({r:/\\<|\\>/g,'<':'&lt;','>':'&gt;'},'<div>'),'&lt;div&gt;','根据正则编码字符串');\n        equal(_util._$encode({r:/\\d/g,'9':'t'},'99999'),'ttttt','编码字符串');\n        equal(_util._$escape('<a>util</a>&'),'&lt;a&gt;util&lt;/a&gt;&amp;','编码html代码');\n        equal(_util._$unescape('&lt;&amp;a&gt;util&lt;/a&gt;'),'<&a>util</a>','反编码html代码');\n        notEqual(_util._$format(new Date(),'yyyy-MM-dd'),'2012-01-11','格式化时间');\n        equal(_util._$fixed(3.1415926,2),'3.14','浮点数值保留指定位数小数点');\n//        equal(_util._$dom2xml(_node),'<div xmlns=\\\"http://www.w3.org/1999/xhtml\\\" id=\\\"js-node\\\">node</div>','将dom节点转为xml串');\n//        equal(document.body.appendChild(_util._$xml2dom('<div xmlns=\"http://www.w3.org/1999/xhtml\" id=\"js-node2\">node</div>')),document.getElementById('js-node2'),'将xml串转为dom节点然后加到页面上，自己跟自己做比较');\n        var _obj = {\"div\":\"node\"};\n//        equal(_util._$dom2object(_node,{}).div,_obj.div,'拷贝页面节点到空对象，跟现有节点比较');\n        //返回的对象为{div:'node'}\n\t\tvar _xml = '<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\\\n\t\t<netease>\\\n\t\t  <albums>\\\n\t\t      <p><id><code><id>id</id>\\\n                  <code>code</code>\\\n                  <name>name</name>\\</code></id></p>\\\n\t\t\t  <album>\\\n\t\t\t      <id>id</id>\\\n\t\t\t\t  <code>code</code>\\\n\t\t\t\t  <name>name</name>\\\n\t\t\t  </album>\\\n\t\t  </albums>\\\n\t\t</netease>';\n\t\tvar _xml2 = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\\n<netease>\\\n<albums>\\\n    <code>1</code>\\\n    <album>\\\n        <id>198114001</id>\\\n        <name></name>\\\n        <desc></desc>\\\n        <auth>2</auth>\\\n        <privacy>2</privacy>\\\n        <count>110</count>\\\n        <tcover>4/zxeW5iOfq3ppXe1etviJwg==/611645124409898904.jpg</tcover>\\\n        <coverurl>1/_0CvRVkR39uuLIIEHVSAJQ==/1278740819214249961.jpg</coverurl>\\\n        <coverurl160>5/eoc7HI1101yikVJnzbBADg==/3082713944952843165.jpg</coverurl160>\\\n    </album>\\\n</albums>\\\n</netease>';\n        var _obj2 = {123:\"123\",abc:\"abc\"};\n        equal(_util._$string2object('abc=abc,123=123',',').abc,_obj2.abc,'key-value字符串转对象');\n        equal(_util._$object2string(_obj2),'123=123,abc=abc','key-value对象转成key=value对后用分隔符join');\n        equal(_util._$query2object('abc=abc&123=123').abc,_obj2.abc,'查询串转对象');\n        equal(_util._$query2object('abc=abc&123=123')['123'],_obj2['123'],'查询串转对象');\n        equal(_util._$object2query(_obj2),'123=123&abc=abc','查询串转对象');\n        var _map = {0:'0',1:'1',2:'2',length:3};\n        equal(_util._$object2array(_map)[1],'1','对象转数组');\n        equal(typeof(_util._$randString()),'string','随机一个字符串');\n        var _str = _util._$randNumberString();\n        var _isNumber = function(_str){\n            try{\n                if(/[^\\d]/.test(_str))\n                    return false;\n                return true;\n            }catch(e){\n                return false;\n            }\n        };\n        equal(_isNumber(_str),true,'随机生成一个全部为数字的字符串，可指定长度');\n        var _num = _util._$randNumber(0,1000);\n        equal(typeof(_num) == 'number' && _num > 0 && _num < 1000,true,'随机生成一个数字，可指定范围');\n        var _obj = {a:0};\n        var _f2 = function(){\n            _obj.a = 2;\n        }._$aop(\n        function(){\n            _obj.a = 1;\n        }\n        ,function(){\n            _obj.a = 3;\n        })\n        _f2();\n        equal(_obj.a,3,'AOP增强操作');\n        var _list = [0,1,2];\n        _util._$forEach(_list,function(_item,_index,_list){\n            equal(_index == _item,true,'foreach回调方法');\n        });\n        var _obj = {a:'1',b:'2',c:'3'};\n        var _value = _util._$forIn(_obj,function(_item,_index,_list){\n            if(_item == '2')\n                return true;\n        });\n        equal(_value,'b','遍历列表或对象');\n        var _list = [0,1,2,3];\n        var _value = _util._$reverseEach(_list,function(_item,_index,_list){\n            _list[_index] = _item+1;\n            return false;\n        });\n        equal(_list[0],1,'逆序遍历列表或对象');\n        var _obj = [1,2,3];\n        var _value = _util._$forIn(_obj,function(_item,_index,_list){\n            if(_item == 2)\n                return true;\n        });\n        equal(_value,1,'forIn找到符合条件的项的索引或标识');\n        var _list = [1,2,3];\n        var _index = _util._$indexOf(_list,function(_value){return _value==2});\n        equal(_index , 1,'线性查找指定项');\n    });\n\n    test('安全删除对象属性',function(){\n        var _obj = {\"a\":\"a\",\"b\":\"b\"};\n        _util._$safeDelete(_obj,[\"a\",\"b\"]);\n        equal(_obj.a,undefined,\"安全删除对象属性\");\n    })\n\n    test('安全删除对象属性',function() {\n        _obj = {\"a\":1,\"b\":2};\n        _util._$safeDelete(_obj,\"b\");\n        equal(_obj.b,undefined,\"安全删除对象属性\");\n    });\n\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}util.test.js',\n          ['{lib}base/util.js'],f);\n});\n\n\n"
  },
  {
    "path": "src/base/util.js",
    "content": "/*\n * ------------------------------------------\n * 通用接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module base/util */\nNEJ.define([\n    './global.js',\n    '{platform}util.js'\n],function(NEJ,_h,_p,_o,_f,_r){\n    /*\n     * 查看数据是否指定类型\n     * @param  {Variable} 数据\n     * @param  {String}   类型\n     * @return {Boolean}  是否指定类型\n     */\n    var _isTypeOf = function(_data,_type){\n        try{\n            _type = _type.toLowerCase();\n            if (_data===null) return _type=='null';\n            if (_data===undefined) return _type=='undefined';\n            return _o.toString.call(_data).toLowerCase()=='[object '+_type+']';\n        }catch(e){\n            return !1;\n        }\n    };\n    /**\n     * 判断是否函数类型\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 返回false\n     *     var is = _u._$isFunction(123);\n     *     // 返回true\n     *     var is = _u._$isFunction(function(){});\n     * });\n     * ```\n     *\n     * @method module:base/util._$isFunction\n     * @param  {Variable} arg0 - 待检测类型的数据\n     * @return {Boolean}         是否函数类型\n     */\n    _p._$isFunction = function(_data){\n        return _isTypeOf(_data,'function');\n    };\n    /**\n     * 判断是否字符串\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 返回false\n     *     var is = _u._$isString(123);\n     *     // 返回true\n     *     var is = _u._$isString(\"123\");\n     * });\n     * ```\n     *\n     * @method module:base/util._$isString\n     * @param  {Variable} arg0 - 待检测类型的数据\n     * @return {Boolean}         是否字符串\n     */\n    _p._$isString = function(_data){\n        return _isTypeOf(_data,'string');\n    };\n    /**\n     * 判断是否数字\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 返回false\n     *     var is = _u._$isNumber(\"123\");\n     *     // 返回true\n     *     var is = _u._$isNumber(123);\n     *     var is = _u._$isNumber(-123);\n     *     var is = _u._$isNumber(Number.MAX_VALUE);\n     * });\n     * ```\n     *\n     * @method module:base/util._$isNumber\n     * @param  {Variable} arg0 - 待检测类型的数据\n     * @return {Boolean}         是否数值类型\n     */\n    _p._$isNumber = function(_data){\n        return _isTypeOf(_data,'number');\n    };\n    /**\n     * 判断是否布尔值\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 返回false\n     *     var is = _u._$isBoolean(0);\n     *     // 返回true\n     *     var is = _u._$isBoolean(false);\n     * });\n     * ```\n     *\n     * @method module:base/util._$isBoolean\n     * @param  {Variable} arg0 - 待检测类型的数据\n     * @return {Boolean}         是否布尔值\n     */\n    _p._$isBoolean = function(_data){\n        return _isTypeOf(_data,'boolean');\n    };\n    /**\n     * 判断是否日期\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 返回false\n     *     var is = _u._$isDate(0);\n     *     // 返回true\n     *     var is = _u._$isDate(new Date());\n     * });\n     * ```\n     *\n     * @method module:base/util._$isDate\n     * @param  {Variable} arg0 - 待检测类型的数据\n     * @return {Boolean}         是否日期\n     */\n    _p._$isDate = function(_data){\n        return _isTypeOf(_data,'date');\n    };\n    /**\n     * 判断是否数组\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 返回false\n     *     var is = _u._$isArray(0);\n     *     // 返回true\n     *     var is = _u._$isArray([1,2]);\n     * });\n     * ```\n     *\n     * @method module:base/util._$isArray\n     * @param  {Variable} arg0 - 待检测类型的数据\n     * @return {Boolean}         是否数组\n     */\n    _p._$isArray = function(_data){\n        return _isTypeOf(_data,'array');\n    };\n    /**\n     * 判断是否对象\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 返回false\n     *     var is = _u._$isObject(function(){});\n     *     // 返回true\n     *     var is = _u._$isObject({});\n     *     var is = _u._$isObject({a:\"a\"});\n     * });\n     * ```\n     *\n     * @method module:base/util._$isObject\n     * @param  {Variable} arg0 - 待检测类型的数据\n     * @return {Boolean}         是否对象\n     */\n    _p._$isObject = function(_data){\n        return _isTypeOf(_data,'object');\n    };\n    /**\n     * 计算字符串长度，中文算两个字符\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 字符串长度为5\n     *     var len = _u._$length('你i他');\n     * });\n     * ```\n     *\n     * @method module:base/util._$length\n     * @param  {String} arg0 - 待计算长度字符串\n     * @return {Number}        字符串长度\n     */\n    _p._$length = (function(){\n        var _reg = /[^\\x00-\\xff]/g;\n        return function(_content){\n            return (''+(_content||'')).replace(_reg,'**').length;\n        };\n    })();\n    /**\n     * 遍历对象\n     * \n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *       var obj = {a:{id:1,name:'a'},b:{id:2,name:'b'},...};\n     * \n     *       // 遍历对象    \n     *       _u._$loop(obj,function(_item,_key){\n     *           // TODO\n     *       });\n     * \n     *       // 从对象里查找id为2的元素，如果有返回KEY，没有返回null\n     *       var key = _u._$loop(obj,function(_item){\n     *           return _item.id==2;\n     *       });\n     * });\n     * ```\n     * \n     * @method module:base/util._$loop\n     * @see    module:base/util._$forIn\n     * @param  {Object}   arg0 - 对象\n     * @param  {Function} arg1 - 回调，如果返回true，则中断遍历\n     * @param  {Object}   arg2 - 回调函数调用时this对象\n     * @return {String}          返回中断时的标识，没有中断则统一返回null\n     */\n    _p._$loop = function(_obj,_callback,_this){\n        if (_p._$isObject(_obj)&&\n            _p._$isFunction(_callback)){\n            return _h.__forIn.apply(_h,arguments);\n        }\n        return null;\n    };\n    /**\n     * 线性查找指定项\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     var list = [\"你\",\"我\",\"他\"];\n     *     // 返回下标1\n     *     var index = _u._$indexOf(list,\"我\");\n     *     // 没有找到，返回-1\n     *     var index = _u._$indexOf(list,\"他们\");\n     *     // 如果第二个参数是过滤接口，根据接口的规则查找\n     *     // 以下规则排除第一个下标\n     *     var index = _u._$indexOf(list,function(_item,_index,_list){\n     *           return _item==='他';\n     *     });\n     * });\n     * ```\n     *\n     * @method module:base/util._$indexOf\n     * @param  {Array}    arg0 - 待搜索列表\n     * @param  {Variable} arg1 - 指定项，如果为function则表示过滤接口\n     * @return {Number}          给定项所在的位置索引，以0开始，没有项返回-1\n     */\n    _p._$indexOf = function(_list,_item){\n        var _filter = _p._$isFunction(_item) ? _item\n                    : function(_value){return _value===_item;},\n            _index  = _p._$forIn(_list,_filter);\n        return _index!=null?_index:-1;\n    };\n    /**\n     * 二分法查找指定项\n     * \n     * 验证函数输入输出说明\n     * \n     * |      | 类型          | 结果说明 |\n     * | :--  | :--      | :-- |\n     * | 输入  | Variable | 中间项元素 |\n     * | 输出  | Number   | < 0  目标元素在低位区间 |\n     * |      |          | = 0  匹配到目标元素 |\n     * |      |          | > 0  目标元素在高位区间 |\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 二分查找id为2的项的索引值\n     *     var list = [{id:1,name:'aaa'},{id:2,name:'bbbb'},...];\n     *     var index = _u._$binSearch(list,function(_item){\n     *         return _item.id-2;\n     *     });\n     * });\n     * ```\n     *\n     * @method module:base/util._$binSearch\n     * @param  {Array}    arg0 - 待查找列表\n     * @param  {Function} arg1 - 验证函数\n     * @return {Number}          找到匹配项索引，找不到返回-1\n     */\n    _p._$binSearch = (function(){\n        var _docheck;\n        // do binary search\n        var _doSearch = function(_list,_low,_high){\n            if (_low>_high) return -1;\n            var _middle = Math.ceil((_low+_high)/2),\n                _result = _docheck(_list[_middle],_middle,_list);\n            if (_result==0)\n                return _middle;\n            if (_result<0)\n                return _doSearch(_list,_low,_middle-1);\n            return _doSearch(_list,_middle+1,_high);\n        };\n        return function(_list,_check){\n            _docheck = _check||_f;\n            return _doSearch(_list,0,_list.length-1);\n        };\n    })();\n    /**\n     * 逆序遍历列表，支持中断\n     * \n     * 回调函数输入输出说明\n     * \n     * |      | 类型          | 说明 |\n     * | :--  | :--      | :-- |\n     * | 输入  | Variable | 值 |\n     * |      | Number   | 下标 |\n     * |      | Array    | 列表对象 |\n     * | 输出  | Boolean  | 是否匹配 |\n     * \n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 删除id为3的项，并退出循环\n     *     var list = [{id:1,name:'aaa'},{id:2,name:'bbbb'},...];\n     *     _u._$reverseEach(list,function(_item,_index,_list){\n     *         if (_item.id==3){\n     *             _list.splice(_index,1);\n     *             return !0;\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method module:base/util._$reverseEach\n     * @see    module:base/util._$forEach\n     * @param  {Array}    arg0 - 列表\n     * @param  {Function} arg1 - 回调，如果返回true，则中断遍历\n     * @param  {Object}   arg2 - 回调函数调用时this对象\n     * @return {Number}          返回遍历中断时的索引值，没有中断则返回null\n     */\n    _p._$reverseEach = function(_list,_callback,_this){\n        if (!!_list&&!!_list.length&&_p._$isFunction(_callback)){\n            for(var i=_list.length-1;i>=0;i--){\n                if (!!_callback.call(_this,_list[i],i,_list)){\n                    return i;\n                }\n            }\n        }\n        return null;\n    };\n    /**\n     * 正序遍历列表，不支持中断\n     * \n     * 回调函数输入输出说明\n     * \n     * |      | 类型          | 说明 |\n     * | :--  | :--      | :-- |\n     * | 输入  | Variable | 值 |\n     * |      | Number   | 下标 |\n     * |      | Array    | 列表对象 |\n     * | 输出  | Boolean  | 是否匹配 |\n     * \n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     var list = [1,2,3];\n     *     _u._$forEach(list,function(_item,_index,_list){\n     *         // TODO somthing\n     *     });\n     * });\n     * ```\n     *\n     * @method module:base/util._$forEach\n     * @see    module:base/util._$reverseEach\n     * @param  {Array}    arg0 - 列表\n     * @param  {Function} arg1 - 回调，如果返回true，则中断遍历\n     * @param  {Object}   arg2 - 回调函数调用时this对象\n     * @return {Void}\n     */\n    _p._$forEach = function(_list,_callback,_this){\n        if (!!_list&&!!_list.length&&\n            _p._$isFunction(_callback)){\n            if (!_list.forEach){\n                _p._$forIn.apply(_p,arguments);\n            }else{\n                _h.__forEach(_list,_callback,_this);\n            }\n        }\n    };\n    /**\n     * 遍历列表或对象，如果带length属性，则作为数组遍历，如果要遍历带length属性的对象用_$loop接口，支持中断退出\n     *\n     * 回调函数输入输出说明\n     * \n     * |      | 类型          | 说明 |\n     * | :--  | :--      | :-- |\n     * | 输入  | Variable | 值 |\n     * |      | Number   | 下标 |\n     * |      | Object_Array | 列表或者集合对象 |\n     * | 输出  | Boolean  | 是否匹配 |\n     * \n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *       // 从有序列表里查找id为2的元素，如果有则返回索引，没有返回null\n     *       var list = [{id:1,name:'a'},{id:2,name:'b'},...];\n     *       var index = _u._$forIn(list,function(_item){\n     *           return _item.id==2;\n     *       });\n     *\n     *       // 从对象里查找id为2的元素，如果有返回KEY，没有返回null\n     *       var obj = {a:{id:1,name:'a'},b:{id:2,name:'b'},...};\n     *       var key = _u._$forIn(obj,function(_item){\n     *           return _item.id==2;\n     *       });\n     * });\n     * ```\n     *\n     * @method module:base/util._$forIn\n     * @param  {Object|Array} arg0 - 列表或者对象\n     * @param  {Function}     arg1 - 回调，如果返回true，则中断遍历\n     * @param  {Object}       arg2 - 回调函数调用时this对象\n     * @return {String|Number}       返回中断时的索引或者标识，没有中断则统一返回null\n     */\n    _p._$forIn = function(_list,_callback,_this){\n        if (!_list||!_p._$isFunction(_callback)){\n            return null;\n        }\n        if (_p._$isNumber(_list.length)){\n            // list see as array\n            for(var i=0,l=_list.length;i<l;i++){\n                if (!!_callback.call(_this,_list[i],i,_list)){\n                    return i;\n                }\n            }\n        }else if (_p._$isObject(_list)){\n            // list is object\n            return _p._$loop(_list,_callback,_this);\n        }\n        return null;\n    };\n    /**\n     * 编码字符串，\n     * 编码规则对象中r正则表达式参数提取字符串需要编码的内容，\n     * 然后使用编码规则对象中的映射表进行替换\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 把字符串99999根据规则9替换成t，结果：ttttt\n     *     var str = _u._$encode({r:/\\d/g,'9':'t'},'99999');\n     * });\n     * ```\n     *\n     * @method module:base/util._$encode\n     * @param  {Object} arg0 - 编码规则\n     * @param  {String} arg1 - 待编码的字串\n     * @return {String}        编码后的字串\n     */\n    _p._$encode = function(_map,_content){\n        _content = ''+_content;\n        if (!_map||!_content){\n            return _content||'';\n        }\n        return _content.replace(_map.r,function($1){\n            var _result = _map[!_map.i?$1.toLowerCase():$1];\n            return _result!=null?_result:$1;\n        });\n    };\n    /**\n     * 编码html代码，'<' -> '&amp;lt;'\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 编码，结果：&amp;lt;a&amp;gt;util&amp;lt;/a&amp;gt;&amp;amp;\n     *     var str = _u._$escape('<a>util</a>&');\n     * });\n     * ```\n     *\n     * @method module:base/util._$escape\n     * @see    module:base/util._$unescape\n     * @param  {String} arg0 - 待编码串\n     * @return {String}        编码后的串\n     */\n    _p._$escape = (function(){\n        var _reg = /<br\\/?>$/,\n            _map = {\n                r:/\\<|\\>|\\&|\\r|\\n|\\s|\\'|\\\"/g,\n                '<':'&lt;','>':'&gt;','&':'&amp;',' ':'&nbsp;',\n                '\"':'&quot;',\"'\":'&#39;','\\n':'<br/>','\\r':''\n            };\n        return function(_content){\n            _content = _p._$encode(_map,_content);\n            return _content.replace(_reg,'<br/><br/>');\n        };\n    })();\n    /**\n     * 反编码html代码，'&amp;lt;' -> '<' \n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 反编码，结果：<&a>util</a>\n     *     var str = _u._$unescape('&amp;lt;&amp;amp;a&amp;gt;util&amp;lt;/a&amp;gt;');\n     * });\n     * ```\n     *\n     * @method module:base/util._$unescape\n     * @see    module:base/util._$escape\n     * @param  {String} arg0 - 待反编码串\n     * @return {String}        反编码后的串\n     */\n    _p._$unescape = (function(){\n        var _map = {r:/\\&(?:lt|gt|amp|nbsp|#39|quot)\\;|\\<br\\/\\>/gi,'&lt;':'<','&gt;':'>','&amp;':'&','&nbsp;':' ','&#39;':\"'\",'&quot;':'\"','<br/>':'\\n'};\n        return function(_content){\n            return _p._$encode(_map,_content);\n        };\n    })();\n    /**\n     * 格式化时间，yyyy|yy|MM|cM|eM|M|dd|d|HH|H|mm|ms|ss|m|s|w\n     *\n     * 各标识说明：\n     * \n     * | 标识  | 说明 |\n     * | :--  | :-- |\n     * | yyyy | 四位年份，如2001 |\n     * | yy   | 两位年费，如01 |\n     * | MM   | 两位月份，如08 |\n     * | M    | 一位月份，如8 |\n     * | dd   | 两位日期，如09 |\n     * | d    | 一位日期，如9 |\n     * | HH   | 两位小时，如07 |\n     * | H    | 一位小时，如7 |\n     * | mm   | 两位分钟，如03 |\n     * | m    | 一位分钟，如3 |\n     * | ss   | 两位秒数，如09 |\n     * | s    | 一位秒数，如9 |\n     * | ms   | 毫秒数，如234 |\n     * | w    | 中文星期几，如一 |\n     * | ct   | 12小时制中文后缀，上午/下午 |\n     * | et   | 12小时制英文后缀，A.M./P.M. |\n     * | cM   | 中文月份，如三 |\n     * | eM   | 英文月份，如Mar |\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 根据格式输出时间，比如:2012-01-11,连接符可自定义\n     *     var str = _u._$format(new Date(),'yyyy-MM-dd');\n     * });\n     * ```\n     *\n     * @method module:base/util._$format\n     * @param  {Number|String|Date} arg0 - 时间\n     * @param  {String}             arg1 - 格式\n     * @return {String}                    指定格式的时间串\n     */\n    _p._$format = (function(){\n        var _map = {i:!0,r:/\\byyyy|yy|MM|cM|eM|M|dd|d|HH|H|mm|ms|ss|m|s|w|ct|et\\b/g},\n            _12cc = ['上午','下午'],\n            _12ec = ['A.M.','P.M.'],\n            _week = ['日','一','二','三','四','五','六'],\n            _cmon = ['一','二','三','四','五','六','七','八','九','十','十一','十二'],\n            _emon = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sept','Oct','Nov','Dec'];\n        var _fmtnmb = function(_number){\n            _number = parseInt(_number)||0;\n            return (_number<10?'0':'')+_number;\n        };\n        var _fmtclc = function(_hour){\n            return _hour<12?0:1;\n        };\n        return function(_time,_format,_12time){\n            if (!_time||!_format)\n                return '';\n            _time = _p._$var2date(_time);\n            _map.yyyy = _time.getFullYear();\n            _map.yy   = (''+_map.yyyy).substr(2);\n            _map.M    = _time.getMonth()+1;\n            _map.MM   = _fmtnmb(_map.M);\n            _map.eM   = _emon[_map.M-1];\n            _map.cM   = _cmon[_map.M-1];\n            _map.d    = _time.getDate();\n            _map.dd   = _fmtnmb(_map.d);\n            _map.H    = _time.getHours();\n            _map.HH   = _fmtnmb(_map.H);\n            _map.m    = _time.getMinutes();\n            _map.mm   = _fmtnmb(_map.m);\n            _map.s    = _time.getSeconds();\n            _map.ss   = _fmtnmb(_map.s);\n            _map.ms   = _time.getMilliseconds();\n            _map.w    = _week[_time.getDay()];\n            var _cc   = _fmtclc(_map.H);\n            _map.ct   = _12cc[_cc];\n            _map.et   = _12ec[_cc];\n            if (!!_12time){\n                _map.H = _map.H%12;\n            }\n            return _p._$encode(_map,_format);\n        };\n    })();\n    /**\n     * 日期字符串转日期对象\n     * \n     * 字符串日期格式同ECMA规范定义：YYYY-MM-DDTHH:mm:ss.sssZ\n     * \n     * 各标识说明：\n     * \n     * | 标识 | 说明 |\n     * | :--  | :-- |\n     * | YYYY | 四位年份，0000-9999，如2001 |\n     * | -    | 年月日分隔符 |\n     * | MM   | 两位月份，01-12，如03 |\n     * | DD   | 两位日期，01-31，如07 |\n     * | T    | 时间起始标识 |\n     * | HH   | 两位小时，00-24，如05 |\n     * | :    | 时分秒分隔符 |\n     * | mm   | 两位分钟，00-59，如30 |\n     * | ss   | 两位秒数，00-59，如08 |\n     * | .    | 秒/毫秒分隔符 |\n     * | sss  | 三位毫秒数，000-999，如004 |\n     * | Z    | 时区偏移 |\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 输入YYYY-MM-DDTHH:mm:ss.sssZ格式字符串，生成日期对象\n     *     var date = _u._$var2date('2013-07-29T13:12:45.300');\n     *\n     *     // 输入YYYY-MM-DDTHH:mm:ss格式字符串，生成日期对象\n     *     var date = _u._$var2date('2013-07-29T13:12:45');\n     *\n     *     // 输入YYYY-MM-DD格式字符串，生成日期对象\n     *     var date = _u._$var2date('2013-07-29');\n     * });\n     * ```\n     *\n     * @method module:base/util._$var2date\n     * @param  {String} arg0 - 日期串\n     * @return {Date}          日期对象\n     */\n    _p._$var2date = function(_time){\n        var _date = _time;\n        if (_p._$isString(_time)){\n            _date = new Date(\n                _h.__str2time(_time)\n            );\n        }\n        if (!_p._$isDate(_date)){\n            _date = new Date(_time);\n        }\n        return _date;\n    };\n    /**\n     * 浮点数值保留指定位数小数点\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 保留2位小数，返回3.14\n     *     var value = _u._$fixed(3.14159,2);\n     * });\n     * ```\n     *\n     * @method module:base/util._$fixed\n     * @param  {Float}  arg0 - 浮点数\n     * @param  {Number} arg1 - 小数位\n     * @return {Number}        浮点数\n     */\n    _p._$fixed = function(_float,_fraction){\n        return parseFloat(new Number(_float).toFixed(_fraction));\n    };\n    /**\n     * 相对路径转绝对路径\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 相对路径../a/b.html转绝对路径http://a.b.com:8010/a/b.html\n     *     var url = _u._$absolute(\n     *         '../a/b.html',\n     *         'http://a.b.com:8010/z/'\n     *     );\n     * });\n     * ```\n     * \n     * @method module:base/util._$absolute\n     * @param  {String} arg0 - 相对路径\n     * @param  {String} arg1 - 绝对路径ROOT，必须以http://开始，默认为location目录\n     * @return {String}        绝对路径地址\n     */\n    _p._$absolute = (function(){\n        var _reg0 = /([^\\/:])\\/.*$/,\n            _reg1 = /\\/[^\\/]+$/,\n            _reg2 = /[#\\?]/,\n            _base = location.href.split(/[?#]/)[0],\n            _anchor = document.createElement('a');\n        // fix for relative protocol, e.g //a.b.com/a\n        var _isAbsolute = function(_uri){\n            _uri = _uri||'';\n            return _uri.indexOf('://')>0||\n                   _uri.indexOf('//')===0;\n        };\n        var _doFormat = function(_uri){\n            return (_uri||'').split(_reg2)[0]\n                             .replace(_reg1,'/');\n        };\n        var _doMergeURI = function(_uri,_root){\n            // for /a/b/c\n            if (_uri.indexOf('/')==0)\n                return _root.replace(_reg0,'$1')+_uri;\n            // for a/b or ./a/b or ../a/b\n            return _doFormat(_root)+_uri;\n        };\n        _base = _doFormat(_base);\n        return function(_uri,_root){\n            _uri = (_uri||'').trim();\n            // check url\n            if (!_isAbsolute(_root))\n                _root = _base;\n            if (!_uri) return _root;\n            // fix relative protocol error\n            if (_uri.indexOf('//')===0){\n                var arr = _root.split(':');\n                _uri = arr[0]+':'+_uri;\n            }\n            if (_isAbsolute(_uri))\n                return _uri;\n            _uri = _doMergeURI(_uri,_root);\n            _anchor.href = _uri;\n            _uri = _anchor.href;\n            return _isAbsolute(_uri) ? _uri :\n                _anchor.getAttribute('href',4); // ie6/7;\n        };\n    })();\n    /**\n     * 从URL地址中提取源信息\n     * \n     * * http://a.b.com:8080/a/b/ -> http://a.b.com:8080\n     * * /a/b -> \n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 提取url地址的源信息\n     *     // 返回http://a.b.com:8080\n     *     var origin = _u._$url2origin(\"http://a.b.com:8080/a/b/\");\n     * });\n     * ```\n     *\n     * @method module:base/util._$url2origin\n     * @param  {String} arg0 - URL地址\n     * @return {String}        源信息\n     */\n    _p._$url2origin = (function(){\n        var _reg = /^([\\w]+?:\\/\\/.*?(?=\\/|$))/i;\n        return function(_url){\n            _url = _url||'';\n            // fix relative protocol\n            if (_url.indexOf('//')===0){\n                _url = location.protocol+_url;\n            }\n            // dump origin\n            if (_reg.test(_url))\n                return RegExp.$1.toLowerCase();\n            return '';\n        };\n    })();\n    /**\n     * key-value字符串转对象\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     var str = \"abc=abc,123=123\";\n     *     // 返回对象{abc:\"abc\",123:\"123\"}\n     *     var obj = _u._$string2object(_str,\",\");\n     * });\n     * ```\n     *\n     * @method module:base/util._$string2object\n     * @see    module:base/util._$object2string\n     * @param  {String}           arg0 - 待处理数据\n     * @param  {String|RegExp}    arg1 - 分隔符\n     * @param  {Boolean|Function} arg2 - 是否反编码\n     * @return {Object}           转换后对象\n     */\n    _p._$string2object = function(_string,_split,_decode){\n        var _obj = {};\n        // decode function\n        var _func = _decode;\n        if (!_p._$isFunction(_func)){\n            _func = function(v){\n                return !_decode?v:decodeURIComponent(v);\n            };\n        }\n        // parse string\n        _p._$forEach(\n            (_string||'').split(_split),\n            function(_name){\n                var _brr = _name.split('=');\n                if (!_brr||!_brr.length) return;\n                var _key = _brr.shift();\n                if (!!_key){\n                    _obj[_func(_key)] = _func(_brr.join('='));\n                }\n            }\n        );\n        return _obj;\n    };\n    /**\n     * key-value对象转成key=value对后用分隔符join\n     * \n     * 对象中不同类型的取值规则如下：\n     * \n     * | 类型            |  取值规则 |\n     * | :--       | :-- |\n     * | Function  |  过滤掉，不输出 |\n     * | Date      |  转成时间戳，getTime取值 |\n     * | Array     |  值用逗号分隔，如[1,2,3] -> 1,2,3 |\n     * | Object    |  使用JSON转成字符串 |\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 返回字符串 abc=abc,123=123\n     *     var obj = {\n     *         abc:\"abc\",\n     *         123:\"123\"\n     *     };\n     *     var str = _u._$object2string(obj);\n     *\n     *     // 返回字符串\n     *     // a=1871406603152186&b=1,2,3&d={\"a\":\"a\",\"b\":\"b\"}&e=e&f=1&g=true\n     *     var obj = {\n     *         a:new Date,\n     *         b:[1,2,3],\n     *         c:function(){},\n     *         d:{a:'a',b:'b'},\n     *         e:'e',\n     *         f:1,\n     *         g:true\n     *     };\n     *     var str = _u._$object2string(obj,'&');\n     * });\n     * ```\n     *\n     * @method module:base/util._$object2string\n     * @see    module:base/util._$string2object\n     * @param  {Object}  arg0 - 对象\n     * @param  {String}  arg1 - 分隔符，默认为逗号\n     * @param  {Boolean|Function} arg2 - 是否编码\n     * @return {String}         key-value串\n     */\n    _p._$object2string = function(_object,_split,_encode){\n        if (!_object) return '';\n        var _arr = [];\n        // encode function\n        var _func = _encode;\n        if (!_p._$isFunction(_func)){\n            _func = function(v){\n                return !_encode?v:encodeURIComponent(v);\n            };\n        }\n        // parse object\n        _p._$loop(\n            _object,function(_value,_key){\n                if (_p._$isFunction(_value)){\n                    return;\n                }\n                if (_p._$isDate(_value)){\n                    _value = _value.getTime();\n                }else if(_p._$isArray(_value)){\n                    _value = _value.join(',');\n                }else if(_p._$isObject(_value)){\n                    _value = JSON.stringify(_value);\n                }\n                _arr.push(_func(_key)+'='+_func(_value));\n            }\n        );\n        return _arr.join(_split||',');\n    };\n    /**\n     * 查询串转对象\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 返回对象{abc:\"abc\",123:\"123\"}\n     *     var obj = _u._$query2object(\"abc=abc&123=123\");\n     * });\n     * ```\n     *\n     * @method module:base/util._$query2object\n     * @see    module:base/util._$object2query\n     * @see    module:base/util._$string2object\n     * @param  {String} arg0 - 查询串\n     * @return {Object}        转换出来的对象\n     */\n    _p._$query2object = function(_query){\n        return _p._$string2object(_query,'&',!0);\n    };\n    /**\n     * 对象转查询串\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 返回对象123=123&abc=abc\n     *     var query = _u._$object2query({abc:\"abc\",123:\"123\"});\n     * });\n     * ```\n     *\n     * @method module:base/util._$object2query\n     * @see    module:base/util._$query2object\n     * @see    module:base/util._$object2string\n     * @param  {Object} arg0 - 对象\n     * @return {String}        查询串\n     */\n    _p._$object2query = function(_object){\n        return _p._$object2string(_object,'&',!0);\n    };\n    /**\n     * 集合转数组，集合具有length属性\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 返回数组['1','2','3']\n     *     var map = {0:'0',1:'1',2:'2',length:3};\n     *     var arr = _u._$object2array(map);\n     *\n     *     // 多用于对节点集合的转换\n     *     var nodes = document.body.childNodes;\n     *     var arr = _u._$object2array(nodes);\n     * });\n     * ```\n     *\n     * @method module:base/util._$object2array\n     * @see    module:base/util._$array2object\n     * @param  {Object} arg0 - 集合，必须有length属性\n     * @return {Array}         数组\n     */\n    _p._$object2array = function(_object){\n        return _h.__col2array(_object);\n    };\n    /**\n     * 数组转对象，将列表中元素按照指定KEY组成对象<br/>\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 输出结果为 {2:{id:2,name:'b'},...}\n     *     var arr = [{id:1,name:'a'},{id:2,name:'b'},...];\n     *     var obj = _u._$array2object(\n     *         arr,function(_item){\n     *             // 过滤name为a的项\n     *             if (_item.name=='a'){\n     *                 return;\n     *             }\n     *             // 组对象的KEY用每项的id\n     *             return _item.id;\n     *         }\n     *     );\n     *\n     *     // 默认使用每项的值组对象\n     *     var brr = ['a','b','c',...];\n     *     // 输出 {a:'a',b:'b',c:'c',...}\n     *     var obj = _u._$array2object(brr);\n     * });\n     * ```\n     *\n     * @method module:base/util._$array2object\n     * @see    module:base/util._$object2array\n     * @param  {Array}    arg0 - 列表\n     * @param  {Function} arg1 - 过滤函数，返回每一项的KEY，没有返回则过滤当前项\n     * @return {Object}   对象\n     */\n    _p._$array2object = function(_list,_filter){\n        var _result = {};\n        _p._$forEach(\n            _list,function(_item){\n                var _key = _item;\n                if (!!_filter){\n                    _key = _filter(_item);\n                }\n                if (_key!=null){\n                    _result[_key] = _item;\n                }\n            }\n        );\n        return _result;\n    };\n    /**\n     * 格式化数字为指定位数，不足位数前面用0补足\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 2    -> 002\n     *     // 22   -> 022\n     *     // 222  -> 222\n     *     // 2222 -> 2222\n     *     var str = _u._$number2string(2,3);\n     * });\n     * ```\n     *\n     * @method module:base/util._$number2string\n     * @param  {Number} arg0 - 数值\n     * @param  {Number} arg1 - 位数，至少1位\n     * @return {String}        格式化后字符串\n     */\n    _p._$number2string = function(_number,_limit){\n        var _len1 = (''+_number).length,\n            _len2 = Math.max(1,parseInt(_limit)||0),\n            _delta = _len2-_len1;\n        if (_delta>0){\n            _number = new Array(_delta+1).join('0')+_number;\n        }\n        return ''+_number;\n    };\n    /**\n     * 安全删除属性，\n     * 部分浏览器（如低版本IE）禁止直接delete节点上的属性\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 节点上保存的数据\n     *     _node.data = {a:'aaaaa',b:'bbbbb'};\n     *     _node.test = 'aaaaa';\n     *\n     *     // 删除单个属性\n     *     _u._$safeDelete(_node,'test');\n     *     // 批量删除\n     *     _u._$safeDelete(_node,['test','data']);\n     * });\n     * ```\n     *\n     * @method module:base/util._$safeDelete\n     * @param  {Object}       arg0 - 对象\n     * @param  {String|Array} arg1 - 属性\n     * @return {Void}\n     */\n    _p._$safeDelete = function(_object,_name){\n        if (!_p._$isArray(_name)){\n            try{\n                delete _object[_name];\n            }catch(e){\n                _object[_name] = undefined;\n            }\n        }else{\n            _p._$forEach(\n                _name,function(_item){\n                    _p._$safeDelete(_object,_item);\n                }\n            );\n        }\n    };\n    /**\n     * 随机一个字符串\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 可能返回\"13d1r1dt2\"\n     *     var seed = _u._$randString(9);\n     * });\n     * ```\n     *\n     * @method module:base/util._$randString\n     * @param  {String} arg0 - 字符串长度\n     * @return {String}        随机字符串\n     */\n    _p._$randString = (function(){\n        var _chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz';\n        return function(_length){\n            _length = _length||10;\n            var _result = [];\n            for(var i=0,_rnum;i<_length;++i){\n                _rnum = Math.floor(Math.random()*_chars.length);\n                _result.push(_chars.charAt(_rnum));\n            }\n            return _result.join('');\n        };\n    })();\n    /**\n     * 随机生成一个给定范围的整数\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 可能返回3\n     *     var seed = _u._$randNumber(0,9);\n     * });\n     * ```\n     * \n     * @method module:base/util._$randNumber\n     * @see    module:base/util._$randNumberString\n     * @param  {Number} arg0 - 小区间，包含\n     * @param  {Number} arg1 - 大区间，不包含\n     * @return {Number}        随机整数\n     */\n    _p._$randNumber = function(_min,_max){\n        return Math.floor(Math.random()*(_max-_min)+_min);\n    };\n    /**\n     * 随机生成一个全部为数字的字符串\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 可能返回123456789\n     *     var seed = _u._$randNumberString(9);\n     * });\n     * ```\n     *\n     * @deprecated\n     * @method module:base/util._$randNumberString\n     * @see    module:base/util._$randNumber\n     * @see    module:base/util._$uniqueID\n     * @param  {Number} arg0 - 随机字符串的长度[1,30]\n     * @return {String}        随机生成的字符串\n     */\n    _p._$randNumberString = function(_length){\n        _length = Math.max(0,Math.min(_length||8,30));\n        var _min = Math.pow(10,_length-1),_max = _min*10;\n        return _p._$randNumber(_min,_max).toString();\n    };\n    /**\n     * 生成系统中的唯一标识，每次调用均生成一个新的标识\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_p){\n     *    // 可能返回123456789\n     *    var _id1 = _p._$uniqueID(),\n     *        _id2 = _p._$uniqueID();\n     *    // _id1 != _id2\n     * });\n     * ```\n     *\n     * @method module:base/util._$uniqueID\n     * @return {String} 唯一标识\n     */\n    _p._$uniqueID = (function(){\n        var _seed = +new Date;\n        return function(){\n            return ''+(_seed++);\n        };\n    })();\n    /**\n     * 读取上下文中指定名字空间的值\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     var obj = {\n     *         a:{\n     *             b:{\n     *                 c:{\n     *                     d:'ddddd'\n     *                 }\n     *             }\n     *         }\n     *     };\n     *     // 输出 ddddd\n     *     var value = _u._$query(obj,'a.b.c.d');\n     *     // 输出 undefined\n     *     var value = _u._$query(null,'a.b.c.d');\n     * });\n     * ```\n     *\n     * @method module:base/util._$query\n     * @param  {Object} arg0 - 上下文\n     * @param  {String} arg1 - 名字空间\n     * @return {Varaible}      查询到的值\n     */\n    _p._$query = function(_context,_namespace){\n        _context = _context||_o;\n        var _arr = (_namespace||'').split('.');\n        for(var i=0,l=_arr.length;i<l;i++){\n            _context = _context[_arr[i]];\n            if (!_context) break;\n        }\n        return _context;\n    };\n    /**\n     * 合并数据，同名属性右侧覆盖左侧，\n     * 最后一个如果是函数则用做数据过滤，\n     * 第一个参数作为合并数据结果集对象，如果为空则新建对象\n     * \n     * 过滤接口输入输出说明\n     * \n     * |      | 类型          | 说明 |\n     * | :--  | :--      | :-- |\n     * | 输入  | Variable | 值 |\n     * |      | String   | 键 |\n     * | 输出  | Boolean  | 是否过滤 |\n     * \n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 合并多个数据至obj0中\n     *     var obj0 = {a:0,b:1},\n     *         obj1 = {a:\"a\",b:\"b\",c:\"c\"},\n     *         obj2 = {c:\"c\",d:\"d\",e:\"f\"},\n     *         ... ;\n     *     var obj = _u._$merge(obj0,obj1,obj2,...);\n     *\n     *     // 带过滤接口合并\n     *     // 阻止a属性的覆盖\n     *     var obj = _u._$merge(\n     *         obj0,obj1,obj2,...,\n     *         function(_value,_key){\n     *             return _key=='a';\n     *         }\n     *     );\n     * });\n     * ```\n     *\n     * @method module:base/util._$merge\n     * @see    module:base/util._$fetch\n     * @param  {Object}   arg0 - 原始对象\n     * @param  {Object}   arg1 - 待拷贝对象\n     * @param  {Function} arg2 - 过滤接口\n     * @return {Object}          拷贝后对象\n     */\n    _p._$merge = function(){\n        var _last = arguments.length-1,\n            _filter = arguments[_last];\n        // check filter function for last args\n        if (_p._$isFunction(_filter)){\n            _last -= 1;\n        }else{\n            _filter = _f;\n        }\n        // args0 as result\n        var _result = arguments[0]||{};\n        // merge\n        for(var i=1;i<=_last;i++){\n            _p._$loop(arguments[i],function(v,k){\n                if (!_filter(v,k)){\n                    _result[k] = v;\n                }\n            });\n        }\n        return _result;\n    };\n    /**\n     * 根据原始对象属性，从目标对象提取非空值\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     var obj0 = {a:0,b:1},\n     *         obj1 = {a:\"a\",b:\"b\",c:\"c\"};\n     *     // 根据obj0的属性,从obj1拷贝非null属性到obj0中\n     *     // 结果是obj0.a = \"a\",obj.b = \"b\",没有拷贝c属性;\n     *     var obj = _u._$fetch(obj0,obj1);\n     * });\n     * ```\n     *\n     * @method module:base/util._$fetch\n     * @see    module:base/util._$merge\n     * @param  {Object} arg0 - 原始对象\n     * @param  {Object} arg1 - 目标对象\n     * @return {Object}        合并后的对象\n     */\n    _p._$fetch = function(_object,_config){\n        if (!!_config){\n            _p._$loop(_object,function(v,k,m){\n                var _value = _config[k];\n                if (_value!=null){\n                    m[k] = _value;\n                }\n            });\n        }\n        return _object;\n    };\n    /**\n     * 判断对象自生是否包含元素\n     * \n     * ```javascript\n     * NEJ.define([\n     *     'base/util'\n     * ],function(_u){\n     *     // 判断空对象是否有属性\n     *     // 输出 false\n     *     var has = _u._$hasProperty({});\n     *       \n     *     // 判断非空对象是否有属性\n     *     // 输出 true\n     *     var has = _u._$hasProperty({a:'a',b:'b',c:'c'});\n     *       \n     *     // 判断空数组是否有属性\n     *     // 输出 false\n     *     var has = _u._$hasProperty([]);\n     *       \n     *     // 判断非空数组是否有属性\n     *     // 输出 true\n     *     var has = _u._$hasProperty([1,2,3]);\n     * });\n     * ```\n     * \n     * @method module:base/util._$hasProperty\n     * @param  {Object|Array} arg0 - 对象\n     * @return {Boolean}             是否有元素\n     */\n    _p._$hasProperty = function(_obj){\n        // for null\n        if (!_obj){\n            return !1;\n        }\n        // for object with length\n        if (_obj.length!=null){\n            return _obj.length>0;\n        }\n        // for object\n        var _length = 0;\n        _p._$loop(_obj,function(){\n            _length++;\n            return _length>0;\n        });\n        return _length>0;\n    };\n    \n    if (CMPT){\n        NEJ.Q  = _p._$query;\n        NEJ.X  = _p._$merge;\n        NEJ.EX = _p._$fetch;\n        NEJ.copy(this.NEJ,NEJ);\n        NEJ.copy(NEJ.P('nej.u'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/define.js",
    "content": "(function(d,p){\n    var __config = {root:{/*lib,pro,platform*/}/*native,charset,global,platform*/},\n        __xqueue  = [], // item:{n:'filename',d:[/* dependency list */],p:[/* platform list */],h:[/* patch list */],f:function}\n        __scache = {}, // uri:STATE   0-loading  1-waiting  2-defined\n        __rcache = {}, // uri:RESULT\n        __stack  = [], // for define stack\n        __platform;\n    /*\n     * 显示日志\n     * @param  {String} _msg 日志内容\n     * @return {Void}\n     */\n    var _doLog = (function(){\n        var _div,_div1,_css1 = {cursor:'pointer',textAlign:'center',backgroundColor:'#ddd'},\n            _css = {display:'none',position:'absolute',top:0,right:0,boder:'1px solid #aaa',overflow:'auto',height:'300px',width:'400px',zIndex:'1000',fontSize:'12px',color:'#fff',backgroundColor:'#000',lineHeight:'20px',textAlign:'left'};\n        return function(_msg){\n            if (!_div){\n                _div = d.createElement('div');\n                var _style = _div.style;\n                for(var x in _css)\n                    _style[x] = _css[x];\n                d.body.appendChild(_div);\n                _div1 = d.createElement('div');\n                _div1.title = '关闭控制台信息';\n                _div1.innerHTML = '×';\n                _style = _div1.style;\n                for(var x in _css1)\n                    _style[x] = _css1[x];\n                _div.appendChild(_div1);\n                _div1.onclick = function(){_div.style.display='none';};\n                d.attachEvent('onkeypress',function(_event){\n                    // press ~ to show console\n                    if (_event.keyCode==96)\n                        _div.style.display = 'block';\n                });\n            }\n            var p = d.createElement('div');\n            p.innerHTML = _msg;\n            _div1.insertAdjacentElement('afterEnd',p);\n        };\n    })();\n    /*\n     * 文件初始化\n     * @return {Void}\n     */\n    var _doInit = function(){\n        if (!p.console&&d.body){\n            p.console = {log:_doLog,warn:_doLog,debug:_doLog,error:_doLog};\n        }\n        // do init add loaded script and remove node\n        var _list = d.getElementsByTagName('script');\n        if (!_list||!_list.length) return;\n        var _reg = /\\/define(?:\\.cmp)?\\.js(?=\\?|#|$)/;\n        for(var i=_list.length-1,_script;i>=0;i--){\n            _script = _list[i];\n            _script.xxx = !0;\n            _reg.test(_script.src)\n                ? _doParseConfig(_script.src)\n                : _doScriptLoaded(_script,!0);\n        }\n        if (!__config.global&&!p.define){\n            p.define = NEJ.define;\n            p.define.nej = !0;\n        }\n    };\n    /*\n     * 解析地址\n     * @param  {String}\n     * @return {Void}\n     */\n    var _doParseConfig = function(_uri){\n        _uri = _doFormatURI(_uri);\n        if (!_uri) return;\n        var _arr = _uri.split(/[?#]/),\n            _brr = _arr[0].split('/');\n        _brr.pop(); // splice define.js\n        var _lib = _brr.join('/')+'/';\n        if (_lib.indexOf('://')<0){\n            // absolute lib path\n            _lib = _doAbsoluteURI(_lib);\n        }\n        __config.root.lib = _lib;\n        var _obj = _doStr2Obj(_arr[1]);\n        __config.charset = _obj.c||'utf-8';\n        __config.global = _obj.g=='true';\n        delete _obj.c;\n        delete _obj.g;\n        _doParsePlatform(_obj.p);\n        delete _obj.p;\n        var _deps = _obj.d;\n        delete _obj.d;\n        var _root = __config.root;\n        for(var x in _obj){\n            _root[x] = _obj[x];\n        }\n        _root.platform = './platform/';\n        if (!_root.pro){\n            _root.pro = '../javascript/';\n        }\n        if (!!_deps){\n            d.write('<script src=\"'+_deps+'\"></scr'+'ipt>');\n        }\n        //console.log(__config.root.lib);\n    };\n    /*\n     * 解析列表依赖关系\n     * @return {Array} 列表\n     */\n    var _doParseDependency = (function(){\n        var _dependency = function(_list,_dmap,_test){\n            if (!_list||!_list.length)\n                return null;\n            var _result = [];\n            for(var i=0,l=_list.length,_file,_files;i<l;i++){\n                _file = _list[i];\n                if (!!_test[_file])\n                    continue;\n                _test[_file] = !0;\n                _files = _dependency(_dmap[_file],_dmap,_test);\n                if (!!_files&&_files.length>0)\n                    _result.push.apply(_result,_files);\n                _result.push(_file);\n            }\n            return _result;\n        };\n        return function(_list,_dmap){\n            return _dependency(_list,_dmap,{});\n        };\n    })();\n    /*\n     * 序列化配置依赖关系\n     * @return {Void}\n     */\n    var _doSerializeDepList = function(_map){\n        if (!_map) return;\n        // format url\n        var _xlist = [],\n            _result = {};\n        for(var x in _map){\n            var _list = _map[x],\n                _file = _doFormatURI(x);\n            _xlist.push(_file);\n            _result[_file] = _list;\n            if (!_list||!_list.length) continue;\n            for(var i=0,l=_list.length;i<l;i++){\n                _list[i] = _doFormatURI(_list[i]);\n            }\n        }\n        // merge result\n        return _doParseDependency(_xlist,_result);\n    };\n    /*\n     * 解析插件信息\n     * @param  {String} _uri 地址\n     * @return {Array}       插件信息\n     */\n    var _doParsePlugin = (function(){\n        var _pmap = {\n            text:function(_uri){\n                _doLoadText(_uri);\n            },\n            json:function(_uri){\n                _doLoadJSON(_uri);\n            },\n            regular:function(_uri){\n                _doLoadText(_uri);\n            },\n            css:function (_uri) {\n                _doLoadStyle(_uri);\n            },\n            res:function(_uri) {\n                __scache[_uri] = 2;\n                __rcache[_uri] = _uri;\n            }\n        };\n        return function(_uri){\n            var _brr = [],\n                _type = null,\n                _arr = _uri.split('!'),\n                _fun = _pmap[_arr[0].toLowerCase()];\n            if (!!_fun){\n                _type = _arr.shift();\n            }\n            _brr.push(_arr.join('!'));\n            _brr.push(_fun||_doLoadScript);\n            _brr.push(_type);\n            return _brr;\n        };\n    })();\n    /*\n     * 初始化平台信息\n     * @param  {String} _config 平台配置信息\n     * @return {Void}\n     */\n    var _doParsePlatform = (function(){\n        var _reg0 = /(cef|ios|win|android)/,\n            _emap = {gk:'G',wk:'W',td:'T'};\n        return function(_config){\n            _config = _config||'td|gk|wk';\n            var _root = __config;\n            // hybrid development\n            if (_reg0.test(_config)){\n                var _name = RegExp.$1;\n                _root.platform = _name=='win'?/T/i:/W/i;\n                _root.native = '{lib}native/'+_name+'/';\n                return;\n            }\n            // parse platform\n            var _reg = [];\n            for(var x in _emap){\n                if (_config.indexOf(x)>=0){\n                    _reg.push(_emap[x]);\n                }\n            }\n            _root.platform = new RegExp(_reg.join('|'),'i');\n        };\n    })();\n    /*\n     * 解析平台识别表达式\n     * @param  {String} 平台识别串\n     * @return {Object} 平台信息，{pkey:'engine',isEngOK:function(_engine){},vkey:'release',isVerOK:function(version){}}\n     */\n    var _doParsePatchExp = (function(){\n        var _reg0 = /\\s/g,\n            _reg1 = /(TR|WR|GR|TV|WV|GV)/i,\n            _reg2 = /([<>=]=?)/,\n            _pkey = '[VERSION]',\n            _emap = {T:'trident',W:'webkit',G:'gecko'},\n            _vmap = {R:'release',V:'version'};\n        var _doParseVersion = function(_exp){\n            return _exp.replace(_reg2,\"'$1'\");\n        };\n        return function(_exp){\n            _exp = (_exp||'').replace(_reg0,'');\n            if (!_reg1.test(_exp)){\n                return null;\n            }\n            var _key = RegExp.$1,\n                _brr = _key.split(''),\n                _result = {\n                    pkey:'engine',\n                    vkey:_vmap[_brr[1]]\n                },\n                _pstr = _emap[_brr[0]];\n            _result.isEngOK = function(_platform){\n                return _platform==_pstr;\n            };\n            var _arr = _exp.split(_key),\n                _left = \"'\"+_doParseVersion(_arr[0])+_pkey+\"'\",\n                _right = \"'\"+_pkey+_doParseVersion(_arr[1])+\"'\";\n            _result.isVerOK = function(_version){\n                var _arr = ['true'];\n                if (!!_left){\n                    _arr.push(_left.replace(_pkey,_version));\n                }\n                if (!!_right){\n                    _arr.push(_right.replace(_pkey,_version));\n                }\n                return eval(_arr.join('&&'));\n            };\n            return _result;\n        };\n    })();\n    /*\n     * 根据给定地址指定请求编码\n     * @param  {String} _uri 地址\n     * @return {String}      编码方式\n     */\n    var _doParseCharset = function(_uri){\n        return _uri.indexOf(__config.root.lib)>=0?'utf-8':__config.charset;\n    };\n    /*\n     * 解析平台依赖的文件\n     * @param  {Array} 依赖列表\n     * @return {Array} 合并了平台信息后的依赖列表\n     */\n    var _doMergePlatform = (function(){\n        var _reg0 = /\\\\|\\//;\n        // {platform}xxx -> ['./platform/xxx','./platform/xxx.patch']\n        // {platform}xxx.yy -> ['./platform/xxx.yy','./platform/xxx.patch.yy']\n        var _doParsePlatformURI = function(_uri){\n            _uri = (_uri||'').replace(\n                '{platform}',\n                __config.root.platform\n            );\n            var _arr = _uri.split(_reg0),\n                _name = _arr.pop(),\n                _path = _arr.join('/')+'/',\n                _patch = _name.split('.'),\n                _sufix = '';\n            if (_patch.length>1){\n                _sufix = '.'+_patch.pop();\n            }\n            return [\n                _path+_name,\n                _path+_patch.join('.')+'.patch'+_sufix\n            ];\n        };\n        return function(_deps){\n            var _ret = {};\n            for(var i=0,_it;_it=_deps[i];i++){\n                if (_it.indexOf('{platform}')>=0){\n                    _it = _doParsePlatformURI(_it);\n                    _deps[i] = _it[0];\n                    _ret[_it[0]] = _it[1];\n                }\n            }\n            return _ret;\n        };\n    })();\n    /*\n     * 从NEJ.patch中提取依赖列表合并至define依赖列表中\n     * @param  {Array}     define中的依赖列表\n     * @param  {Function}  define执行函数\n     * @return {Array}     合并了patch后的依赖列表\n     */\n    var _doMergePatched = function(_callback){\n        var _func = _callback.toString();\n        if (_func.indexOf('NEJ.patch')<0){\n            return;\n        }\n        var _ret = [],\n            _map = {},\n            _tmp = NEJ.patch,\n            _reg = __config.platform;\n        NEJ.patch = function(){\n            var _args = _doFormatARG.apply(\n                null,arguments\n            );\n            // check platform\n            if (!_args[0]||!_args[1]||\n                !_reg.test(_args[0])){\n                return;\n            }\n            // merge dependency\n            for(var i=0,l=_args[1].length,_it;i<l;i++){\n                _it = _args[1][i];\n                if (!_map[_it]){\n                    _map[_it] = !0;\n                    _ret.push(_it);\n                }\n            }\n        };\n        try{\n            _callback();\n        }catch(e){\n            // ignore\n        }\n        NEJ.patch = _tmp;\n        return _ret;\n    };\n    /*\n     * 判断是否字符串\n     * @param  {Varable} _data 数据\n     * @param  {String}  _type 类型\n     * @return {Boolean}       是否字符串\n     */\n    var _isTypeOf = function(_data,_type){\n        return Object.prototype.toString.call(_data)==='[object '+_type+']';\n    };\n    /*\n     * 取事件触发元素\n     * @param  {Event} _event 事件对象\n     * @return {Void}\n     */\n    var _getElement = function(_event){\n        return !_event?null:(_event.target||_event.srcElement);\n    };\n    /*\n     * 查询串转对象\n     * @param  {String} _query 查询串\n     * @return {Object}        对象\n     */\n    var _doStr2Obj = function(_query){\n        var _result = {},\n            _list = (_query||'').split('&');\n        if (!!_list&&!!_list.length)\n            for(var i=0,l=_list.length,_brr,_key;i<l;i++){\n                _brr = _list[i].split('=');\n                _key = _brr.shift();\n                if (!_key) continue;\n                _result[decodeURIComponent(_key)] =\n                        decodeURIComponent(_brr.join('='));\n            }\n        return _result;\n    };\n    /*\n     * 相对路径转绝对路径\n     * @param  {String} 相对路径\n     * @return {String} 绝对路径\n     */\n    var _doAbsoluteURI = (function(){\n        var _xxx = !1,\n            _anchor = d.createElement('a');\n        var _append = function(){\n            if (_xxx) return;\n            _xxx = !0;\n            _anchor.style.display = 'none';\n            (d.body||d.getElementsByTagName('head')[0]).appendChild(_anchor);\n        };\n        return function(_uri){\n            _append();\n            _anchor.href = _uri;\n            _uri = _anchor.href;\n            return _uri.indexOf('://')>0&&_uri.indexOf('./')<0 ?\n                   _uri : _anchor.getAttribute('href',4); // ie6/7\n        };\n    })();\n    /*\n     * 格式化地址,取绝对路径\n     * @param  {String} _uri 待格式化地址\n     * @return {String}      格式化后地址\n     */\n    var _doFormatURI = (function(){\n        var _reg = /{(.*?)}/gi,\n            _reg1= /([^:])\\/+/g,\n            _reg3= /[^\\/]*$/,\n            _reg4= /\\.js$/i,\n            _reg5= /^[{\\/\\.]/,\n            _reg6= /(file:\\/\\/)([^\\/])/i,\n            _reg7= /([^:])\\/\\//g;\n        var _absolute = function(_uri){\n            return _uri.indexOf('://')>0;\n        };\n        var _slash = function(_uri){\n            return _uri.replace(_reg1,'$1/');\n        };\n        \n        var _root = function(_uri) {\n            return _uri.replace(_reg3,'');\n        };\n        var _format = function(_uri){\n            return _doAbsoluteURI(\n                _uri.replace(_reg7,'$1/')   // fix ie8 http://a.b.com:80/a//b//c/d.js error\n                    .replace(_reg6,'$1/$2') // fix mac file:// error\n            );\n        };\n        var _amdpath = function(_uri,_type){\n            // start with {xx} or /xx/xx or ./ or ../\n            // end with .js\n            // absolute uri\n            if (_reg4.test(_uri)||\n                _reg5.test(_uri)||\n                _absolute(_uri)){\n                return _uri;\n            }\n            // lib/base/klass -> {lib}base/klass.js\n            // pro/util/a     -> {pro}util/a.js\n            var _arr = _uri.split('/'),\n                _path = __config.root[_arr[0]],\n                _sufx = !_type?'.js':'';\n            if (!!_path){\n                _arr.shift();\n                return _path+_arr.join('/')+_sufx;\n            }\n            // for base/klass -> {lib}base/klass.js\n            return '{lib}'+_arr.join('/')+_sufx;\n        };\n        return function(_uri,_base,_type){\n            if(_isTypeOf(_uri,'Array')){\n                var _list = [];\n                for(var i = 0; i < _uri.length; i++){\n                    _list.push(\n                        _doFormatURI(_uri[i],_base,_type)\n                    );\n                }\n                return _list;\n            }\n            if (!_uri) return '';\n            if (_absolute(_uri)){\n                return _format(_uri);\n            }\n            if (_base&&_uri.indexOf('.')==0){\n                //console.log('before root uri '+_uri);\n                _uri = _root(_base)+_uri;\n                //console.log('after root uri '+_uri);\n            }\n            _uri = _slash(_amdpath(_uri,_type));\n            var _uri = _uri.replace(\n                _reg,function($1,$2){\n                    return __config.root[$2]||$2;\n                }\n            );\n            return _format(_uri);\n        };\n    })();\n    /*\n     * 格式化输入参数\n     * @param  {String}   字符串\n     * @param  {Array}    数组\n     * @param  {Function} 函数\n     * @return {Array}    格式化后的参数列表\n     */\n    var _doFormatARG = function(_str,_arr,_fun){\n        var _args = [null,null,null],\n            _kfun = [\n                function(_arg){return _isTypeOf(_arg,'String');},\n                function(_arg){return _isTypeOf(_arg,'Array');},\n                function(_arg){return _isTypeOf(_arg,'Function');}\n            ];\n        for(var i=0,l=arguments.length,_it;i<l;i++){\n            _it = arguments[i];\n            for(var j=0,k=_kfun.length;j<k;j++){\n                if (_kfun[j](_it)){\n                    _args[j] = _it;\n                    break;\n                }\n            }\n        }\n        return _args;\n    };\n    /*\n     * 侦测脚本载入情况\n     * @param  {Node} _script 脚本节点\n     * @return {Void}\n     */\n    var _doAddListener = (function(){\n        var _statechange = function(_event){\n            var _element = _getElement(_event)||this;\n            if (!_element) return;\n            var _state = _element.readyState;\n            if (_state==='loaded'||\n                _state==='complete')\n                _doScriptLoaded(_element,!0);\n        };\n        return function(_script){\n            if (!_script.onload){\n                _script.onload = function(e){_doScriptLoaded(_getElement(e),!0);};\n                _script.onerror = function(e){_doScriptLoaded(_getElement(e),!1);};\n                _script.onreadystatechange = _statechange;\n            }else{\n                _script.xxx = !0;\n            }\n        };\n    })();\n    /*\n     * 页面已存在的script节点添加事件检测\n     * @return {Void}\n     */\n    var _doAddAllListener = (function(){\n        var _reg = /(?:NEJ\\.)?define\\s*\\(/;\n        var _isNEJInline = function(_script){\n            var _code = _script.innerHTML;\n            return _code.search(_reg)>=0;\n        };\n        var _isNEJTemplate = function(type){\n            return (type||'').search(/^nej\\//i)===0;\n        };\n        return function(){\n            var _list = d.getElementsByTagName('script');\n            for(var i=_list.length-1,_script;i>=0;i--){\n                _script = _list[i];\n                if (_isNEJTemplate(_script.type)){\n                    continue;\n                }\n                if (!_script.xxx){\n                    _script.xxx = !0;\n                    if (!_script.src&&_isNEJInline(_script)){\n                        _doClearStack();\n                    }else{\n                        _doAddListener(_list[i]);\n                    }\n                }\n            }\n        };\n    })();\n    /*\n     * 清理脚本节点\n     * @param  {Node} _script 脚本节点\n     * @return {Void}\n     */\n    var _doClearScript = function(_script){\n        if (!_script||!_script.parentNode) return;\n        _script.onload = null;\n        _script.onerror = null;\n        _script.onreadystatechange = null;\n        _script.parentNode.removeChild(_script);\n    };\n    /*\n     * 检查所有文件是否都载入\n     * @return {Boolean} 是否都载入\n     */\n    var _isFinishLoaded = function(){\n        for(var x in __scache)\n            if (__scache[x]===0)\n                return !1;\n        return !0;\n    };\n    /*\n     * 检查列表是否都载入完成\n     * @param  {Array} 列表\n     * @return {Void}\n     */\n    var _isListLoaded = function(_list){\n        if (!!_list&&!!_list.length){\n            for(var i=_list.length-1;i>=0;i--){\n                if (__scache[_list[i]]!==2){\n                    return !1;\n                }\n            }\n        }\n        return !0;\n    };\n    /*\n     * 检查集合是否都载入完成\n     * @param  {Object} 集合\n     * @return {Void}\n     */\n    var _isMapLoaded = function(_map){\n        if (!!_map){\n            for(var x in _map){\n                if (__scache[_map[x]]!==2){\n                    return !1;\n                }\n            }\n        }\n        return !0;\n    };\n    /*\n     * 载入依赖文本\n     * @param  {String} _uri 文本地址\n     * @return {Void}\n     */\n    var _doLoadText = (function(){\n        var _msid,\n            _msxml = [\n                'Msxml2.XMLHTTP.6.0',\n                'Msxml2.XMLHTTP.3.0',\n                'Msxml2.XMLHTTP.4.0',\n                'Msxml2.XMLHTTP.5.0',\n                'MSXML2.XMLHTTP',\n                'Microsoft.XMLHTTP'\n            ];\n        var _getXHR = function(){\n            if (!!p.XMLHttpRequest){\n                return new p.XMLHttpRequest();\n            }\n            if (!!_msid){\n                return new ActiveXObject(_msid);\n            }\n            for(var i=0,l=_msxml.length,_it;i<l;i++){\n                try{\n                    _it = _msxml[i];\n                    var _xhr = new ActiveXObject(_it);\n                    _msid = _it;\n                    return _xhr;\n                }catch(e){\n                    // ignore\n                }\n            }\n        };\n        return function(_uri,_callback){\n            if (!_uri) return;\n            var _state = __scache[_uri];\n            if (_state!=null) return;\n            // load text\n            __scache[_uri] = 0;\n            var _xhr = _getXHR();\n            _xhr.onreadystatechange = function(){\n                if (_xhr.readyState==4){\n                    var _text = _xhr.responseText||'';\n                    __scache[_uri] = 2;\n                    __rcache[_uri] = _text;\n                    if (!!_callback){\n                        _callback(_text);\n                    }\n                    _doCheckLoading();\n                }\n            };\n            _xhr.open('GET',_uri,!0);\n            _xhr.send(null);\n        };\n    })();\n    /*\n     * 载入依赖JSON\n     * @param  {String} _uri JSON地址\n     * @return {Void}\n     */\n    var _doLoadJSON = function(_uri){\n        _doLoadText(_uri,function(_text){\n            var _data;\n            try{\n                if (!!p.JSON&&!!JSON.parse){\n                    _data = JSON.parse(_text);\n                }else{\n                    _data = eval('('+_text+')');\n                }\n            }catch(ex){\n                _data = null;\n            }\n            __rcache[_uri] = _data;\n        });\n    };\n    /*\n     * 载入依赖脚本\n     * @param  {String} _uri 脚本地址\n     * @return {Void}\n     */\n    var _doLoadScript = function(_uri){\n        if (!_uri) return;\n        var _state = __scache[_uri];\n        if (_state!=null) return;\n        // load file\n        __scache[_uri] = 0;\n        var _script = d.createElement('script');\n        _script.xxx = !0;\n        _script.type = 'text/javascript';\n        _script.charset = _doParseCharset(_uri);\n        _doAddListener(_script);\n        _script.src = _uri;\n        (d.getElementsByTagName('head')[0]||d.body).appendChild(_script);\n    };\n    /**\n     * 外联载入依赖样式\n     *\n     * @param  {String} _uri 样式地址\n     * @return {Void}\n     */\n    var _doLoadStyle = function (_uri) {\n        if (!_uri) return;\n        var _state = __scache[_uri];\n        if (_state!=null) return;\n        // load state as done\n        __scache[_uri] = 2;\n        __rcache[_uri] = ' ';\n        // load style link\n        var link = d.createElement('link');\n        link.rel = 'stylesheet';\n        (d.getElementsByTagName('head')[0]||d.body).appendChild(link);\n        link.href = _uri;\n    };\n    /*\n     * 脚本载入完成回调\n     * @param  {Node}    _script 脚本节点对象\n     * @param  {Boolean} _isok   脚本载入是否成功\n     * @return {Void}\n     */\n    var _doScriptLoaded = function(_script,_isok){\n        var _uri = _doFormatURI(_script.src);\n        if (!_uri) return;\n        var _arr = __stack.pop();\n        if (!!_arr){\n            _arr.unshift(_uri);\n            _doDefine.apply(p,_arr);\n        }\n        // 404 is ok for platform\n        if (!!_uri&&__scache[_uri]!=1){\n            __scache[_uri] = 2;\n        }\n        _doClearScript(_script);\n        _doCheckLoading();\n    };\n    /*\n     * 搜索循环引用\n     * @return {Object} 需解环项\n     */\n    var _doFindCircularRef = (function(){\n        var _result;\n        var _index = function(_array,_name){\n            for(var i=_array.length-1;i>=0;i--)\n                if (_array[i].n==_name)\n                    return i;\n            return -1;\n        };\n        var _loop = function(_item){\n            if (!_item) return;\n            var i = _index(_result,_item.n);\n            if (i>=0) return _item;\n            _result.push(_item);\n            var _deps = _item.d;\n            if (!_deps||!_deps.length) return;\n            for(var i=0,l=_deps.length,_citm;i<l;i++){\n                _citm = _loop(__xqueue[_index(__xqueue,_deps[i])]);\n                if (!!_citm) return _citm;\n            }\n        };\n        var _exec = function(_list,_pmap){\n            if (!_pmap) return;\n            // find platform patch list\n            var _arr = [];\n            for(var i=0,l=_list.length,_it;i<l;i++){\n                _it = _list[i];\n                if (_pmap[_it]){\n                    _arr.push(_it);\n                }\n            }\n            // index queue by file name\n            var _map = {};\n            for(var i=0,l=__xqueue.length,_it;i<l;i++){\n                _it = __xqueue[i];\n                _map[_it.n] = _it;\n            }\n            // execute platform patch\n            for(var i=0,l=_arr.length,_it,_item;i<l;i++){\n                _it = _arr[i];\n                // exec hack.js\n                _item = _map[_it];\n                if (!!_item){\n                    _doExecFunction(_item);\n                }\n                // exec hack.patch.js\n                _item = _map[_pmap[_it]];\n                if (!!_item){\n                    _doExecFunction(_item);\n                }\n            }\n        };\n        return function(){\n            _result = [];\n            // check from begin to end\n            var _item = _loop(__xqueue[0]);\n            // must do platform before excute\n            if (!!_item){\n                _exec(_item.d,_item.p);\n            }\n            return _item;\n        };\n    })();\n    /*\n     * 执行文件脚本\n     * @param  {Object} 缓存信息\n     * @return {Void}\n     */\n    var _doExecFunction = (function(){\n        // dependency inject param\n        var _f = function(){return !1;};\n        // merge inject param\n        var _doMergeDI = function(_dep,_map){\n            var _arr = [];\n            if (!!_dep){\n                // merge dependency list result\n                for(var i=0,l=_dep.length,_it;i<l;i++){\n                    _it = _dep[i];\n                    // except for 404 platform\n                    if (!__rcache[_it]&&!_map[_it]){\n                        __rcache[_it] = {};\n                    }\n                    // result of (platform.js || platform.patch.js)\n                    _arr.push(__rcache[_it]||__rcache[_map[_it]]||{});\n                }\n            }\n            _arr.push({},{},_f,[]); // p,o,f,r\n            return _arr;\n        };\n        var _doMergeResult = function(_uri,_result){\n            var _ret = __rcache[_uri],\n                _iso = {}.toString.call(_result)=='[object Object]';\n            if (!!_result){\n                if (!_ret||!_iso){\n                    // for other type of return\n                    _ret = _result;\n                }else{\n                    // for namespace return\n                    _ret = _ret||{};\n                    for(var x in _result){\n                        _ret[x] = _result[x];\n                    }\n                }\n            }\n            __rcache[_uri] = _ret;\n            // save platform information\n            var _puri = __config.root.lib+'base/platform.js';\n            if (_uri===_puri){\n                __platform = _ret;\n            }\n        };\n        return function(_item){\n            var _args = _doMergeDI(\n                _item.d,_item.p\n            );\n            if (!!_item.f){\n                var _result = _item.f.apply(p,_args)||\n                              _args[_args.length-4];\n                _doMergeResult(_item.n,_result);\n            }\n            __scache[_item.n] = 2;\n            console.log('do '+_item.n);\n        };\n    })();\n    /*\n     * 检查依赖载入情况\n     * @return {Void}\n     */\n    var _doCheckLoading = function(){\n        if (!__xqueue.length) return;\n        for(var i=__xqueue.length-1,_item;i>=0;){\n            _item = __xqueue[i];\n            if (__scache[_item.n]!==2&&\n               (!_isMapLoaded(_item.p)||\n                !_isListLoaded(_item.h)||\n                !_isListLoaded(_item.d))){\n                i--; continue;\n            }\n            // for loaded\n            __xqueue.splice(i,1);\n            if (__scache[_item.n]!==2){\n                _doExecFunction(_item);\n            }\n            i = __xqueue.length-1;\n        }\n        // check circular reference\n        if (__xqueue.length>0&&_isFinishLoaded()){\n            var _item = _doFindCircularRef()||__xqueue.pop();\n            console.warn('try to unlock circular reference -> '+_item.n);\n            _doExecFunction(_item);\n            _doCheckLoading();\n        }\n    };\n    /*\n     * 清理函数定义缓存栈\n     * @return {Void}\n     */\n    var _doClearStack = function(){\n        var _args = __stack.pop();\n        while(!!_args){\n            _doDefine.apply(p,_args);\n            _args = __stack.pop();\n        }\n    };\n    /*\n     * 查找当前执行的脚本\n     * @return {Node} 当前执行脚本\n     */\n    var _doFindScriptRunning = function(){\n        // for ie8+\n        var _list = d.getElementsByTagName('script');\n        for(var i=_list.length-1,_script;i>=0;i--){\n            _script = _list[i];\n            if (_script.readyState=='interactive'){\n                return _script;\n            }\n        }\n    };\n    /*\n     * 执行模块定义\n     * @param  {String}   _uri      当前所在文件，确定文件中模块不会被其他文件依赖时可以不用传此参数，比如入口文件\n     * @param  {Array}    _deps     模块依赖的其他模块文件，没有依赖其他文件可不传此参数\n     * @param  {Function} _callback 模块定义回调【必须】\n     * @return {Void}\n     */\n    var _doDefine = (function(){\n        var _seed = +new Date,\n            _keys = ['d','h'];\n        var _doComplete = function(_list,_base){\n            if (!_list||!_list.length) return;\n            for(var i=0,l=_list.length,_it;i<l;i++){\n                _it = _list[i]||'';\n                if(_it.indexOf('.')!=0) continue;\n                _list[i] = _doFormatURI(_it,_base);\n            }\n        };\n        return function(_uri,_deps,_callback){\n            // check input\n            var _args = _doFormatARG.apply(\n                p,arguments\n            );\n            _uri = _args[0]||\n                   _doFormatURI('./'+(_seed++)+'.js');\n            _deps = _args[1];\n            _callback = _args[2];\n            // check module defined in file\n            _uri = _doFormatURI(_uri);\n            if (__scache[_uri]===2){\n                return; // duplication\n            }\n            // for {platform}\n            var _plts;\n            if (!!_deps){\n                _plts = _doMergePlatform(_deps);\n            }\n            // for NEJ.patch\n            var _pths;\n            if (!!_callback){\n                _pths = _doMergePatched(_callback);\n            }\n            // complete relative uri\n            _doComplete(_deps,_uri);\n            __scache[_uri] = 1;\n            // push to load queue\n            var _xmap = {\n                n:_uri,d:_deps,\n                h:_pths,f:_callback\n            };\n            __xqueue.push(_xmap);\n            // load dependence\n            for(var i=0,l=_keys.length,_it,_list;i<l;i++){\n                _it = _keys[i];\n                _list = _xmap[_it];\n                if (!!_list&&!!_list.length){\n                    var _kmap = {};\n                    for(var k=0,j=_list.length,_itt,_itm,_arr,_type;k<j;k++){\n                        _itt = _list[k];\n                        if (!_itt){\n                            console.warn('empty dep uri for '+_uri);\n                        }\n                        // 0 - url\n                        // 1 - load function\n                        // 2 - resource type\n                        _arr = _doParsePlugin(_itt);\n                        _itm = _doFormatURI(_arr[0],_uri,_arr[2]);\n                        _kmap[_itt] = _itm;\n                        _list[k] = _itm;\n                        // load resource\n                        _arr[1](_itm);\n                    }\n                    if (_it==='h'&&!!_xmap.f){\n                        _xmap.f.kmap = _kmap;\n                    }\n                }\n            }\n            if (!!_plts){\n                var _pmap = {};\n                for(var x in _plts){\n                    _it = _doFormatURI(_plts[x],_uri);\n                    _pmap[_doFormatURI(x,_uri)] = _it;\n                    _doLoadScript(_it);\n                }\n                _xmap.p = _pmap;\n            }\n            // check state\n            _doCheckLoading();\n        };\n    })();\n    // exports\n    /**\n     * NEJ名字空间\n     * @namespace NEJ\n     */\n    p.NEJ = {};\n    // only for test\n    p.NEJ.dump = function(){\n        return {\n            state:__scache,\n            result:__rcache,\n            queue:__xqueue\n        };\n    };\n    /**\n     * 模块定义，单个文件只允许定义一个模块，即只允许执行一次NEJ.define，模块执行函数支持依赖列表注入和名字空间两种方式\n     * \n     * 文件路径遵循以下规则\n     *  \n     *  * 完整的文件路径，如 http://a.b.com/patch/to/file.js\n     *  * 使用{}标识配置参数，如{root}file.js\n     *  * 直接使用非{}标识配置参数，此时不能加.js后缀，系统自动加.js后缀，如 root/file\n     *  * NEJ库文件可以省略lib标识，如base/element，等价于 lib/base/element，等价于 {lib}base/element.js\n     *  * 其他文本资源采用text!前缀标识，如text!/path/to/file.css，注意开发时如果资源是跨域的请设置好浏览器XHR的跨域支持\n     *  * JSON资源采用json!前缀标识，如json!/path/to/data.json，注意开发时如果资源是跨域的请设置好浏览器XHR的跨域支持\n     *  * Regular模板资源采用regular!前缀标识，如regular!/path/to/file.html，注意开发时如果资源是跨域的请设置好浏览器XHR的跨域支持\n     *  * 路径以 ./ 或者 ../ 开始的相对路径则相对于当前脚本文件的路径，如 ./util.js\n     *\n     * ```javascript\n     * // 依赖base/global和base/util\n     * NEJ.define([\n     *    'base/global',\n     *    'base/util'\n     * ],function(NEJ,u,p,o,f,r){\n     *     // u - {lib}base/util.js文件返回的api集合\n     *     // p - 允许外界调用的类或者API均定义在p空间下\n     *     // o - 注入的空对象 {}\n     *     // f - 注入的空函数 function(){return !1;}\n     *     // r - 注入的空数组 []\n     *\n     *     // TODO something\n     *\n     *     // 返回允许外界使用的对象\n     *     return p;\n     * });\n     * ```\n     *\n     * ```javascript\n     * // 不依赖其他文件，等价于直接执行\n     * NEJ.define(function(p,o,f,r){\n     *     // TODO something\n     *\n     *     return p;\n     * });\n     * ```\n     *\n     * ```javascript\n     * // 仅用于引入依赖文件列表而不执行业务逻辑\n     * NEJ.define(['base/global']);\n     * ```\n     *\n     * @method NEJ.define\n     * @param  {String}   arg0 - 当前文件路径标识，不传自动解析，建议不传此参数\n     * @param  {Array}    arg1 - 模块依赖的其他模块文件，没有依赖其他文件可不传此参数\n     * @param  {Function} arg2 - 模块定义回调，依赖列表中文件返回的执行结果会依次注入此回调中，回调返回的结果可被其他文件依赖时注入\n     * @return {Void}\n     */\n    NEJ.define = function(_uri,_deps,_callback){\n        // has uri\n        if (_isTypeOf(_uri,'String'))\n            return _doDefine.apply(p,arguments);\n        // without uri\n        var _args = [].slice.call(arguments,0),\n            _script = _doFindScriptRunning();\n        // for ie check running script\n        if (!!_script){\n            var _src = _script.src;\n            if (!!_src)\n                _args.unshift(_doFormatURI(_src));\n            return _doDefine.apply(p,_args);\n        }\n        // for other\n        __stack.push(_args);\n        _doAddAllListener();\n    };\n    /**\n     * 根据条件判断是否在当前平台执行，\n     * 平台支持TR|WR|GR，没有比较操作符表示支持当前内核所有release版本\n     *\n     *  | 标识符 | 说明 |\n     *  | :--   | :-- |\n     *  | T     | Trident引擎，如ie |\n     *  | W     | Webkit引擎，如chrome |\n     *  | G     | Gecko引擎，如firefox |\n     *\n     * 平台内置的Trident引擎版本对应的IE版本关系：\n     *\n     *  | Trident版本 | IE版本 |\n     *  | :-- | :-- |\n     *  | 2.0 | 6   |\n     *  | 3.0 | 7   |\n     *  | 4.0 | 8   |\n     *  | 5.0 | 9   |\n     *  | 6.0 | 10  |\n     *  | 7.0 | 11  |\n     *\n     * patch文件必须符合以下规则：\n     * * 只允许执行若干NEJ.patch\n     * * NEJ.patch中只允许修改hack.js注入的对象里的API\n     * * 定义函数必须返回hack.js注入的对象\n     *\n     * ```javascript\n     * NEJ.define([\n     *     './hack.js'\n     * ],function(h,p,o,f,r){\n     *     // 针对trident平台的处理逻辑\n     *     NEJ.patch('TR',function(){\n     *         // TODO\n     *         console.log('from inline ie');\n     *         h.api = function(){\n     *             // TODO\n     *         };\n     *     });\n     *\n     *     // 针对webkit平台的处理逻辑\n     *     NEJ.patch('WR',['./hack.chrome.js'],function(wk){\n     *         // TODO\n     *         console.log('from inline chrome');\n     *     });\n     *\n     *     // 针对gecko平台的处理逻辑\n     *     NEJ.patch('GR',['./hack.firefox.js'],function(gk){\n     *         // TODO\n     *         console.log('from inline firefox');\n     *     });\n     *\n     *     // 针对IE6平台的处理逻辑\n     *     NEJ.patch('TR==2.0',['./hack.ie6.js']);\n     *\n     *     // 针对IE7-IE9的处理逻辑\n     *     NEJ.patch('3.0<=TR<=5.0',function(){\n     *         // TODO\n     *         console.log('from inline ie7-ie9');\n     *     });\n     *\n     *     // 必须返回hack.js注入的对象\n     *     return h;\n     * });\n     * ```\n     *\n     * @method NEJ.patch\n     * @param  {String}   arg0 - 平台识别条件，如：6<=TR<=9\n     * @param  {Array}    arg1 - 依赖文件列表\n     * @param  {Function} arg2 - 执行函数\n     * @return {Void}\n     */\n    NEJ.patch = function(_exp,_deps,_callback){\n        var _args = _doFormatARG.apply(\n            null,arguments\n        );\n        if (!_args[0]) return;\n        // check platform\n        var _kernel = __platform._$KERNEL,\n            _result = _doParsePatchExp(_args[0]);\n        if (!!_result&&!!_args[2]&&\n            _result.isEngOK(_kernel[_result.pkey])&&\n            _result.isVerOK(_kernel[_result.vkey])){\n            var _argc = [],\n                _deps = _args[1];\n            if (!!_deps){\n                var _xmap = arguments.callee.caller.kmap||{};\n                for(var i=0,l=_deps.length;i<l;i++){\n                    _argc.push(__rcache[_xmap[_deps[i]]]||{});\n                }\n            }\n            _args[2].apply(p,_argc);\n        }\n    };\n    /**\n     * 载入依赖配置，对于老项目或者使用第三方框架的项目，可以使用此接口配置\n     *\n     * 项目某个页面加载的脚本列表\n     *\n     * ```html\n     * <script src=\"./a.js\"></script>\n     * <script src=\"./b.js\"></script>\n     * <script src=\"./c.js\"></script>\n     * <script src=\"./d.js\"></script>\n     * <script src=\"./e.js\"></script>\n     * <script src=\"./f.js\"></script>\n     * ```\n     *\n     * 根据脚本规则提取文件的依赖关系，没有依赖其他文件可不配置，假设页面入口文件为f.js\n     *\n     * ```javascript\n     * var deps = {\n     *     '{pro}f.js':['{pro}d.js'],\n     *     '{pro}e.js':['{pro}a.js','{pro}b.js','{pro}c.js'],\n     *     '{pro}c.js':['{pro}b.js'],\n     *     '{pro}b.js':['{pro}a.js']\n     * };\n     * ```\n     *\n     * 通过NEJ.deps配置依赖关系，假设以下配置文件的路径为./deps.js\n     *\n     * ```javascript\n     * NEJ.deps(deps,['{pro}f.js']);\n     * ```\n     *\n     * 修改页面使用文件依赖管理，使用d参数配置依赖文件地址\n     *\n     * ```html\n     *   <script src=\"http://nej.netease.com/nej/src/define.js?d=./deps.js&pro=./\"></script>\n     *   <script src=\"./f.js\"></script>\n     * ```\n     *\n     * 之后项目只需要维护deps.js中的依赖配置信息即可\n     *\n     * 说明：开发阶段deps.js中配置的文件均会被载入页面中，发布上线时仅提取页面使用到的脚本，比如上例中页面只用到f.js，通过配置文件可以发现f.js只依赖了d.js，因此这个页面最终发布时只会导出d.js和f.js\n     *\n     * @method NEJ.deps\n     * @param  {Object} arg0 - 依赖映射表，如'{pro}a.js':['{pro}b.js','{pro}c.js']\n     * @param  {Array}  arg1 - 入口屏蔽文件列表，页面载入依赖配置文件中的文件时不载入此列表中的文件，多为页面入口文件\n     * @return {Void}\n     */\n    NEJ.deps = function(_map,_entry){\n        var _list = _doSerializeDepList(_map);\n        if (!_list||!_list.length) return;\n        // ignore entry list\n        var _map = {};\n        if (!!_entry&&_entry.length>0){\n            for(var i=0,l=_entry.length;i<l;i++){\n                _map[_doFormatURI(_entry[i])] = !0;\n            }\n        }\n        for(var i=_list.length-1;i>=0;i--){\n            if (!!_map[_list[i]]){\n                _list.splice(i,1);\n            }\n        }\n        // load script\n        var _arr = [];\n        for(var i=0,l=_list.length,_it;i<l;i++){\n            _it = _list[i];\n            _arr.push('<script src=\"'+_it+'\"></scr'+'ipt>');\n            __scache[_it] = 2;\n        }\n        d.writeln(_arr.join(''));\n    };\n    /**\n     * 是否兼容模式，兼容模式下支持用全局名字空间使用API和控件\n     *\n     * ```javascript\n     * if (CMPT){\n     *     // TODO something\n     *     // 此中的代码块在打包配置文件中将OBF_COMPATIBLE设置为false情况下打包输出时将被忽略\n     * }\n     * ```\n     *\n     * @name external:window.CMPT\n     * @constant {Boolean}\n     */\n    p.CMPT = !0;\n    /**\n     * 是否调试模式，打包时调试模式下的代码将被过滤\n     *\n     * ```javascript\n     * if (DEBUG){\n     *     // TODO something\n     *     // 此中的代码块在打包发布后被过滤，不会输出到结果中\n     * }\n     * ```\n     *\n     * @name external:window.DEBUG\n     * @constant {Boolean}\n     */\n    p.DEBUG = !0;\n    // init\n    _doInit();\n})(document,window);\n"
  },
  {
    "path": "src/ui/audio/audio.css",
    "content": ".#<uispace>{display:$<box>;$<box-pack>:end;width:150px;height:30px;line-height:30px;overflow:hidden;text-align:left;}\n.#<uispace> .z-ttl{display:block;$<box-flex>:1;overflow-x:$<marquee>;border:2px solid #aaa;background:#fdc;}\n.#<uispace> .z-act{width:30px;background:none center center no-repeat;background-size:30px 30px;cursor:default;}\n.#<uispace> .js-play{background-image:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAV4AAAFeCAYAAADNK3caAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAABoMSURBVHhe7d3Pi1VnnsfxXjU0DDQ09KpXA/MHDMy2oWFWveqV0jsTY1GUERFbB8SWQpAshCBDIhJhQBjThbgoFFukFooYCQot4ohBJBQWRsSWiBgRi0TOnKfHO11t1Fv3nnOee57vfRVIAnXPr+/zft7nU8+553l+8hM/KqACKqACKqACKqACKqACKqACKqACKlBeBTZv3vybDz744D/qf0fr//9L+lf//w/1v8o/NcAABjIy8MMaBx1NXkp+Ks+qbzjjDRs2/Ky+oN/VF3Ss/u9fMxaVyN3MMICBcRj46ytf/S75qygRv/fee/9aS3ax/vecbKUYDGCgUAaSvxaTz3ot4JmZmX+u7xb/XWiRx7k72kaqwsAUMJC8lvzWKwFv2bLlF/WJ/Wct3FXSlW4wgIGgDKwmzyXfTVzA9Un8tj6ZJ0ELLc1MQZrBrhvFKAwk3yXvTUy+9cnu8K0E0I4Crc/iJQgD6dtYO7LKd+PGjT999eRPIpQIMYCBqWUgeTD5sHMB1wf6ZW36L4LctaYWGO0neWKgNQa+SF7sTL6zs7M/rw9wVYO11mDELy1iIAADyYvJj63LN8XpWrjnSZd0MYABDLyRgfOtDzvURv9UsXU4DGAAA29nIHmytdRb72yDYutwGMAABoYzkHzZWL6bNm36le/pDi82INUIAxhIDCRfJm82km+9kz8BClAYwAAG1s9A8ubY4q03/rVir7/YaqVWGMDAgIHkz7Hk6/u6ICISDGBgbAa+GFm80u7Yxfa9zADfyyQb/LfBwMipt97gdBsHtg8AYwAD08pA8ui6U++r14ItySO5Se8YwEAzBtISQ+t7nbi+O6VZxxRcDTCAAQw0Z2B9s5h5qOam48aLAQy0xsDwh2yvFqi0Vlrzu5ykoIYYwEBiYHXowplpZnV3utbudDqejocBDFRDV6yoB4L/SLzEiwEMYKA9BpJX3/nthrrYJxS8vYKrpVpiAAPJq+8Ur4nOQUIUGMBAuwwkrw5LvN8oertFV0/1xMDUM/DNsMT7HUimHhIPhDwQwkCLDNSJ97thiVfBWyy4m5ibGAYwkBggXmJ1c8UABjIzQLyZCy7xSDwYwADxEq+0gwEMZGaAeDMXXNqRdjCAAeIlXmkHAxjIzADxZi64tCPtYAADxEu80g4GMJCZAeLNXHBpR9rBAAaIl3ilHQxgIDMDxJu54NKOtIMBDBAv8Uo7GMBAZgaIN3PBpR1pBwMYIF7ilXYwgIHMDBBv5oJLO9IOBjBAvMQr7WAAA5kZIN7MBZd2pB0MYIB4iVfawQAGMjNAvJkLLu1IOxjAAPESr7SDAQxkZoB4Mxdc2pF2MIAB4iVeaQcDGMjMAPFmLri0I+1gAAPES7zSDgYwkJkB4s1ccGlH2sEABoiXeKUdDGAgMwPEm7ng0o60gwEMEC/xSjsYwEBmBog3c8GlHWkHAxggXuKVdjCAgcwMEG/mgks70g4GMEC8xCvtYAADmRkg3swFl3akHQxggHiJV9rBAAYyM0C8mQsu7Ug7GMAA8RKvtIMBDGRmgHgzF1zakXYwgAHiJV5pBwMYyMwA8WYuuLQj7WAAA8RLvNIOBjCQmQHizVxwaUfawQAGiJd4pR0MYCAzA8SbueDSjrSDAQwQL/FKOxjAQGYGiDdzwaUdaQcDGCBe4pV2MICBzAwQb+aCSzvSDgYwQLzEK+1gAAOZGSDezAWXdqQdDGCAeIlX2sEABjIzQLyZCy7tSDsYwADxEq+0gwEMZGaAeDMXXNqRdjCAAeIlXmkHAxjIzADxZi64tCPtYAADxEu80g4GMJCZAeLNXHBpR9rBAAaIl3ilHQxgIDMDxJu54LnSzv79+6uzZ89W9+7dqwY/jx8/rr7++utqYWGh2rZtm84WtO1zMeY44yd34g3W+bZu3VpdunTp/2X7tv9ZXV2tLly4UG3fvp2AgzFAiOMLMVftiDdQp9u1a9c/JNyh9q0/8Pz58+rEiRPV7OwsAQdiIZdAHGc8yRNvkM6WxJmGEcb9efDgQXXo0CHyDcIDIY4nxFx1I94gHe306dPjOvcftrt582a1b98+Ag7CRS6ROM5ooifeAB1sx44d1YsXL1oRb9rJ999/Xy0tLXkAF4ANQhxNiLnqRbwBOtfx48dbk+7aHT179qxK+84Fo+P0UxLapf12Id4A4r127Von4h3sdGVlpTp48CABB2CFRNuX6Dg1Jd4Anenu3budinew8yT43bt3E3AAZsaRhW3akzbxBuhE3377bRbxpoOk7/+eOXOmSt8X1hHb64hqOV21JF7iHUvaT548qY4ePUq+Afgh/fzSJ94AHSdn4n3d0svLy9WBAwcIOABHBJxPwMQboMNMUrwDEV++fLnauXMnAQfgiYC7FzDxBugofRBvEnD6LvHi4mI1NzdHwAG4IuDuBEy8ATpIX8Q7SL8PHz6sDh8+TL4B2CLfbuRLvAE6R9/EOxDw7du3q/n5eQIOwBgBtytg4g3QKfoq3iTgly9fmn4yAGPES7wS1Gsduc/iHaTfNP1kmoB9ZmZG+xHx1DMg8QboBCWIdyDg+/fvm34yAHMScLMETLwBOkFJ4h0I+MaNG9WePXumPvkQWDOBlVo/4iXesd5ca2Mj009Op3RKlWWb5028xNuGQxvt4+nTp9WxY8ek3wAstimnyPsi3gCwlzjU8CZTm35SAo4s27XXRrzE2yitdrHxlStXTD8ZgMtpkeg410m8AQCPknjXSnww/aTXj6XgccTW922Il3i7CK2t7TPdVEw/Sb59F+mo50e8xNuaJLvcUZp+cv/+/R7ABeB1VElF/DzxBgA54lDD2yR+6dIl008GYDaiTEe5JuINAPE0iXcw/eTJkyer2dlZCTgAv6MIK8pniTcAuNMmXtNPGvMtXcDES7xdDs1m2fetW7eqffv2Sb8BWC5dqOs9f+INAOu0Jt61Vjf9pBS8Xun14XPES7xZUmmugzx79qw6fvy46ScDcN0HQXZ1DsQbAFCJ98daT9NPfvzxx4YfAvDdlfwmuV/iDQAm8b49T1+7ds30kwEYn6Qkuzg28QaAknjfPZCRpp88d+5ctXXrVgk4AO9diDD3Pok3AIjEu74R5CdPnph+MgDvuSXZxfGINwCIxLs+8Q4+laafPHDggPQbgP0upJhjn8QbAD7iHU28g0+bftJX0HJI9k3HIF7iHc9aQbZK00+eOnWqMv0kCeeUMPESbxCFNrsM008SL/EGkGHORjTU0Ey6a7e+c+eO6Sf1v87H/yXeAJARb3viHezJ9JMScJfhiXiJt31rBdnj8+fPqxMnTph+MkAf6VKi4+ybeANAJfF2a/qHDx9Wn3zySed/fo7TgW1TZjInXuLt1lqB9n7z5k3TTwboL324WRFvAJAk3nx2T9NPnj9/vtq2bZsEHKDvTErCxBsAHuLNJ97BkUw/Weaf+JMS7evHJV7izW+tQEdM008ePHhQ+g3Qj3JKmXgDACPxTt7kpp+UgEcRN/ES7+StFeQM0vSTZ86cMf1kgD41ikTH+SzxBoBE4u2XuU0/Kf0OkzHxEm+/rBXobJaXl00/GaB/DZPoOL8n3gBgSLz9tnWafnLXrl0ewAXoa+NI1rSQQRueePst3nR2L168qBYXF00/GbQPjipkiTcACMTbf/EOzjC11ZEjR6TfAP1uVNmu/TzxBgCAeMsR7+BMb9++bfrJAH1vXPkSb4DGJ97yxDs444sXL1bbt2+XgAP0w1EkTLwBGpx4yxVvOnPTT07f18+Il3jLtlags3/w4EF16NAh6TdAnxyWfok3QCNLvIHsW1+K6SfjJ2DiJd5Y1gpyNen146WlJdNPBuifvscbtBEl3iC2fcNlDKafHPanq9+XlZIl3gAyJt644h1c2crKiuknA/TVwQ2SeAM0JvHGF+/gCtP0k7t37/YArvB+S7yFN2C6gxLv9Ig3Xenq6qrpJwvvt8RbeAMS73RJd+3Vpuknjx49Kv0W2IeJt8BGe/1BisQ7vfJNV276ybIerKX+S7zEO93WCnT1ly9frnbu3CkBF9CnibeARhr2VSGJN5A9G16K6SfLSL/ES7wNu7rN+1iBhw8fVocPH5Z+e9q/ibenDTMs5a79vcTbR/X145zS9JPz8/ME3LN+Trw9a5BRhDv4LPH2Q3J9PYuXL19WFy5cMP1kj/o68faoMcaRrq+T9VV3/TuvNP3kwsJCNTMzIwFPuN8T74QbYFzZGmron9hKOaP79++bfnLC/Z54J9wAxFuKruKd540bN6o9e/ZIvxNwAPFOoOhtyFbijSfCSVxRmn7y9OnThh8ye4B4Mxe8beka452EruId86uvvvLyRUYXEG/GYnchXeKNJ8FJXVFaemjbtm2GHjI4gXgzFLkr4fo62aQUFfe4V69eJd4MTiDeDEUm3riiinhlXrjo/rVj4iXeiO5wTQ0qcP78eam3Yy8Qb8cF7jrtGuNtYBibvrECaZ7fHNxO8zGIl3jpRwV+VAEP2bodbiBe4qUdFfhRBazrRrz+7BlyczBJDnO2XQGJl3iJl3jb9or9vaMCxni7la6lfwIMM3i4xqFtV2BpaUnY6dgNxng7LnCOJ7eGGtpWz3Tvb+/evcTbsReIt+MCE+90S6y0q7948SLpZnAC8WYoctfylXhL01s/z3dlZaWanZ0l3gxOIN4MRSbeforGWf29AmltNkvDd/9QbeAC4iVe/pniCqT12M6dO2c+3sweIN7MBe8i/RpqmGJzNrh0KxDnS7iv93viJd4GXdemJVbg0aNH1eHDh43lTrDvE+8Ei99W+pV4S9Rf/nN+8eJFtbi4WM3NzZHuhPs98U64AdqQL/Hml1hpR7xy5YqHZz3q68Tbo8YYV8LEW5oG853v8vJydeDAAQm3Z/2ceHvWIOPIl3jziayUI6X5Fo4dO0a4Pe3fxNvThhlFwMRbig67P8+0XHv6etjWrVtJt8d9m3h73DjrlS/xdi+0Eo5w7dq1as+ePYRbQJ8m3gIaaZiAibcELXZ3jvfv368OHTpEuAX1ZeItqLHeJmDi7U5qfd7z8+fPq88//9xbZwX2YeItsNFeFzDx9lmP7Z9bes33woUL1fbt26XcQvsv8RbacGvlS7zty62ve/Sa7+Re8x025DfK74mXePvqGOe1pgLp5uo13xjStfRPAOla+ie2n73mG0e2axOxxBtAvoYaYso3vea7a9cu47gB+qjZyQI2IvHGEu/du3e95huwn0q8wRqVeGOI12u+MYcV3vTQzVBDAAkTb9niTa/5piXVveZLvH8T8ihfj/DZyUFDvOWK9/r1617zDRB+RvWfxBug0Ym3PPF6zXdyQWVUSXbxeeIl3vKsVfAZp9d8FxYWvOYboN81ETLxBgBA4u2/ib3mO90J19fJAojWXA39F+3aM0yv+e7fv9/3cQP2vXFTr8QbAAaJt58iTu1y5MgRwg3Qx8YV7Nu2I94AUBBvv8TrNV/DCsNETbzE2y9rFX426TXf3bt3S7kB+tUweTb5PfEGAETinbytV1ZWvOYboC81keko2xJvAFiId3Li9ZqvYYVRhDv4LPES7+SsVfCRB6/5btu2zbBCgD40jjybbEO8AaCRePMa/MaNG17zDdBvmoiz6bbEGwAg4s0jXq/5GlZoKlxDDQGEO2hE4u1WvOk13xMnTnjNN1CfaUug4+5H4g0AE/F2J16r+Uq548r1XdsRL/F2Z62C9+w1X8LtQriGGgII11BD+2ZPfz189tlnvqkQqH90KdBx9y3xBgDMUENzAa+urlaLi4vV3Nwc6QboE+MKMdd2xBsAMuJtJl6v+RpWyCVcQw0BhGuooZlw02u+H330kYQbqC/kFui4x5N4A0An8Y4mYK/5SrjjCrOt7YiXeEezVsGfTq/5nj171mq+AZhvS4CT2g/xBoBQ4h1+N7h27ZrXfAOwPilRtn1c4g0AI/G+Xbz37t2rDh48aBw3AOdty2+S+yPeAEAS74/F++zZs+r48eNe8w3A9yQF2dWxiTcAmMT7d/Gm1XyXlpYq0zV6gNaVNNvYL/ES7/AB0kI+cfPmzWrfvn2GFQIw3Ybc+rwP4g0A6bQnXtM1Srd9luybzo14ibeQPPvj0xxM1zg7OyvlBuC4NHk2OV/iDQDstCXeNI5rukYpt4n4Jr0t8RJvUYk3Tdc4Pz8v4QbgdtLym+TxiTcAwNOQeB8+fFgdPnyYcAPwOknh9eXYxBsA5MjiffHixd+mazSOa2ihL9Js4zyIl3h7O9Rw6dKlaufOnVJuAEbbkFWkfRBvAKijJd7l5eVq//79hBuAzUiybPNaiDcA3FHEm67j6NGjhBuAyTYlFXFfxBsA8tLFm5bdOXXqlGV3ArAYUZJdXBPxBoC9ZPFadsdDsy7E1vd9Ei/xTuTh2t27d6sDBw4YVgjAX98l18fzI94A4JeUeC27I+H2UYS5z4l4iTdL4k3L7pw5c8ayOwF4yy2piMcj3gAdoe+J17I7Um5EeTa5JuIl3s4Sb1o+3bI7pNtEUFG3JV7ibV28lt0h26jCbOu6iJd4WxNvGse17A7ptiWnyPshXuJtRbxp2Z29e/f6elgAniILry/XRrwBOsokH65ZdkfC7YvMSjoP4iXesRJvWnZnYWHB8ukB+ClJWFHOlXgDdJycideyOxJuFPlN8jqIN4B4Hz16NFZqHXWjtOyO5dOJd5LCinJs4g0g3iTELn8su0O2UYTXl+sg3gDiTVMqdvGTlt05efKkZXcCMNIX4TiP/7uJE2+ATpX+/G/7x7I7Ui5JdscA8QYQb+ogaV7bNn7u3Llj2Z0gTBBnd+JsWlviDdLJ0qKQjx8/Htu9lt3pbydt2slt37+2Jd4g4k2da35+vnr69OlI8h0snz43N+ets0AskG3/ZLu2TYg3WGfbtWtXdevWrXXJ98svv6x2795NuMEYIN1+S9fDtcAdLk3HmMSaVnwY/KSXH9KSO2lC8iRoHbT/HVQbxWwjiTewfHXamJ1Wu5bfrsRLvJIvBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQmQHizVxwaaX8tKINtWFTBoiXeKUdDGAgMwPEm7ngTe+Utpe2MFA+A8RLvNIOBjCQl4HVd4p38+bN37m7ln931YbaEAP9YaD26rfDEu83Gqw/DaYttAUGymegFu/KsMR7VUOX39DaUBtioD8M1OK9OizxntBg/WkwbaEtMBCCgRPDEu8fNXSIhvbwJO/DE/VW77cyUCfe+XeKd8uWLb8lXuLFAAYw0B4DyavvFO+GDRt+Vhf8uaK3V3S1VEsMTDUDq8mr7xRv+mUNyRdAmWpQ/Nnsz2YMtMfAF0Ol+0q8O4iXeDGAAQy0wsCOdYm3Hgj+ZV3wHxS9laJLDu0lB7VUy9IY+CH5dF3iTR+qP/xn4iVeDGAAA+MzUHv09Lqlmz74/vvv/7uCj19wtVM7DGCgFu9vRhKvh2ygIQ4MYKARA+t7qPa6mWtb/1rhGxW+tPEo52sMFQMtMZD8OXLaHWxQb/wn8iVfDGAAA+tnIHlzbOmmDTdt2vSreidPFH39RVcrtcLA9DKQfJm82Ui8rx60/R5I0wuSttf2GFg/A/UXE37fWLprhhw+Vfz1F1+t1AoD08dAnXY/bU26aUcbN278aQ3SeTBNH0zaXJtjYF0MnE+ebFW8aWezs7M/rxvgfzTCuhrB0+GWng7jDW8FMHA9+bF16a4ZckivE18voBDER3wYwEAOBq6P9FrwuHb+8MMP/6kW70XylUQwgIEpZ+Bi8uG4Lh15u1djvkemvOg57qaOIbVhoJ8MHOlkTHc9Nq4j9gZLwks9bsAYmBYGku+S99bjx04/Uy9r8Yv0NYq68KvTUnzXSTQYmDoGVpPnku86FeqoO69P6F+8Yjx1MPozuJ9/BmuXFtsleS35bVQnZv38zMzMv6V5KCUCEsYABkpmIHks+SyrQJse7NVKFn949Q0IK1q0eAcuGWbnTsY9ZiB5Kn1j6w9ZviLWVLLDtk+rbKYljuuL2VNf1H/V//1L/d9bPW4Af6q5UWAgNgO3Xnko+WhP8tO6VgMeJju/VwEVUAEVUAEVUAEVUAEVUAEVUAEVUAEVUAEVUAEVCF+B/wWXI359gAoiZAAAAABJRU5ErkJggg==\");}\n.#<uispace> .js-pause{background-image:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAV4AAAFeCAYAAADNK3caAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAABU/SURBVHhe7d3Ph6VXHsfxrEIYQsgqq2H+gGG2Icwqq6y6ZddJ/9CLbJowhDB/QRZNIkSGYQhZhTCbiCb0KoQwhOhFGLIKQwiRoqPmnJlqutNJ3edWPfdzvvWcV9ES6lad53zv+/s+n/rep+o+8YQPFVABFVABFVABFVABFVABFVABFVABFbh4Fbh69eoL165d+0v79177/y/6v/b/99u/Y//UAAMYCDJw/yEHvde91P108az6K1d86dKlp9qGXmob+nv773fBohK5wwwDGDgLA9+d+Oql7q8LJeJXXnnlj02yH7V/P5KtFIMBDFxQBrq/Puo+Ky3gGzdu/L6dFv+4oEU+y+noa6QqDEzAQPda91spAV+/fv2ZdmG3m3CPSFe6wQAGNsrAUfdc991wAbeLeLFdzPcbLbQ0M0Gawa6DYh8Guu+694bJt13sLXclgHYfaD0WLxthoN+NdSsq38uXLz958sqfRCgRYgAD0zLQPdh9eHABt4Webaa/u5FTa1pgPH+SJwZWY+Bu9+LB5Hvz5s2n2wKfe8JWe8KIX1rEwAYY6F7sflxdvj1ON+HeIV3SxQAGMPCrDNxZfezQjP62Yms4DGAAA7/NQPfkaqm3fbNLiq3hMIABDOxmoPvy3PK9cuXKc+7T3V1sQKoRBjDQGei+7N48l3zbN/kAUIDCAAYwsJyB7s0zi7d98fOKvbzYaqVWGMDAAwa6P88kX/frgohIMICBMzNwd2/xSrtnLrb7MjdwXybZ4H8NBvZOve0LPl5jYd8DwBjAwKwMdI8uTr0nvxbsLXkkN+kdAxg4HwP9LYaW/TpxO536Xx1TcDXAAAYwcH4Glv0VMy+qOXQcvBjAwGoM7H6R7eQNKr1X2vlPOUlBDTGAgc7A0c43zux/Wd1Jt9pJp/E0HgYwcLzzHSvaIPhN4iVeDGAAA+sx0L166t0NrdgfKvh6BVdLtcQABrpXTxWvP3QOEqLAAAbWZaB7dVfi/VbR1y26eqonBqZn4NtdifcHkEwPiReEvCCEgRUZaIn3h12JV8FXLLhDzCGGAQx0BoiXWB2uGMBAmAHiDRdc4pF4MIAB4iVeaQcDGAgzQLzhgks70g4GMEC8xCvtYAADYQaIN1xwaUfawQAGiJd4pR0MYCDMAPGGCy7tSDsYwADxEq+0gwEMhBkg3nDBpR1pBwMYIF7ilXYwgIEwA8QbLri0I+1gAAPES7zSDgYwEGaAeMMFl3akHQxggHiJV9rBAAbCDBBvuODSjrSDAQwQL/FKOxjAQJgB4g0XXNqRdjCAAeIlXmkHAxgIM0C84YJLO9IOBjBAvMQr7WAAA2EGiDdccGlH2sEABoiXeKUdDGAgzADxhgsu7Ug7GMAA8RKvtIMBDIQZIN5wwaUdaQcDGCBe4pV2MICBMAPEGy64tCPtYAADxEu80g4GMBBmgHjDBZd2pB0MYIB4iVfawQAGwgwQb7jg0o60gwEMEC/xSjsYwECYAeINF1zakXYwgAHiJV5pBwMYCDNAvOGCSzvSDgYwQLzEK+1gAANhBog3XHBpR9rBAAaIl3ilHQxgIMwA8YYLLu1IOxjAAPESr7SDAQyEGSDecMGlHWkHAxggXuKVdjCAgTADxBsuuLQj7WAAA8RLvNIOBjAQZoB4wwWXdqQdDGCAeIlX2sEABsIMEG+44NKOtIMBDBAv8Uo7GMBAmAHiDRdc2pF2MIAB4iVeaQcDGAgzQLzhgks70g4GMEC8xCvtYAADYQaIN1xwaUfawQAGiJd4pR0MYCDMAPGGCy7tSDsYwADxEq+0gwEMhBkg3nDBK6ad999///jrr78+/umnn45HfPR1+/r9OkbVRw2k0CR7xDu5eD/55JMRrv3NNfv1JBugr6UGpJtmjngnFu9bb71VSroPLqZfV6oR1IB0U6w9vA7xTizee/fulRRvv65UM6gB8aZYI96JZfvwk390dFRSvP26Us2gBsSbYo14ifd/Yqv8kWoGNSDeFGvES7zEe8IA8RIv8RJi7Edsiff/wqn8MUII1swcRF5cm1j2pEO8RJsR7S/rTLzEW9K/KSGU3PzJRaVqYJ28fImXeEu6JyWDkpsn3ujILcWaF9cmlu3DTz7pGDWMkI41rx1LvBNLmHiJlwTzY4Zec+Il3pL+TQmh5OaNGowaUg1gnfzJSzoSr77L953EO3HadQ+r+3hJd4x0iZd4y4belBTKFqBdWKoG1skL2Ix3YvmSjlED6ealK/FOLF2jBqMG0h0jXeIl3rKhNyWFsgUwatj0qMWoYWL5ko5RQ+qAs86j6Zp4ibekf1ONWnLz7uPddNo1aphYuma8Zrypw806j8+SJd6J5SvtGTWQ4pgX2IiXeEv6NyWEkps3ajBqSDWAdfInL+lIvPou33dmvBOnXTNeM17SHSNd4iXesqE3JYWyBXAf76bHDWa8E8uXdIwaUgecddzHu+mTdB/AiZd49+HFY9cbTUi8Em9J/6aavOTm3dWw+XBEvMRb0j3E689CphgYsQ7xEi/xlqwA8Y4QYmpN4iXektpJNUDJzRs1GDWkGsA66w3ul9aSdLy4tpQVj1u3PyVeibekf1ONXnLzEq/Em2oA66x7oi6pJ+lIvEs48Zj1e1PilXhL+jfV7CU3L/FKvKkGsM76p+qumpKOxLuLEZ8/TF9KvBJvSf+mGr7k5iVeiTfVANY5zMl6Wl1JR+LVd/m+6zWXeCXekv5NCaHk5iVeiTfVANbJn7ykI/Hqu3zfSbwTp93+5Ff+SAlBDcaIJ/X8Vl3HqGFi+ZKOw6eqmLZ+XcRLvCX9m2q8kps34zXjTTWAdfI/8pGOxKvv8n1nxjtx2jXj9WaXpDtGusRLvGVDb0oKZQvQLixVA+vkBWzGO7F8SceogXTz0pV4J5auUYNRA+mOkS7xEm/Z0JuSQtkCGDVsetRi1DCxfEnHqCF1wFnn0XRNvMRb0r+pRi25effxbjrtGjVMLF0zXjPe1OFmncdnyRLvxPKV9owaSHHMC2zES7wl/ZsSQsnNGzUYNaQawDr5k5d0JF59l+87M96J064Zrxkv6Y6RLvESb9nQm5JC2QK4j3fT4wYz3onlSzpGDakDzjru4930SboP4MRLvPvw4rHrjSYkXom3pH9TTV5y8+5q2Hw4Il7iLeke4vVnIVMMjFiHeImXeEtWgHhHCDG1JvESb0ntpBqg5OaNGowaUg1gnfUG90trSTpeXFvKiset258Sr8Rb0r+pRi+5eYlX4k01gHXWPVGX1JN0JN4lnHjM+r0p8Uq8Jf2bavaSm5d4Jd5UA1hn/VN1V01JR+LdxYjPH6YvJV6Jt6R/Uw1fcvMSr8SbagDrHOZkPa2upCPx6rt83/WaS7wSb0n/poRQcvMSr8SbagDr5E9e0pF49V2+7yTeidNuf/Irf6SEoAZjxJN6fquuY9QwsXxJx+FTVUxbvy7iJd6S/k01XsnNm/Ga8aYawDr5H/lIR+LVd/m+M+OdOO2a8XqzS9IdI13iJd6yoTclhbIFaBeWqoF18gI2451YvqRj1EC6eelKvBNL16jBqIF0x0iXeIm3bOhNSaFsAYwaNj1qMWqYWL6kY9SQOuCs82i6Jl7iLenfVKOW3Lz7eDeddo0aJpauGa8Zb+pws87js2SJd2L5SntGDaQ45gU24iXekv5NCaHk5o0ajBpSDWCd/MlLOhKvvsv3nRnvxGnXjNeMl3THSJd4ibds6E1JoWwB3Me76XGDGe/E8iUdo4bUAWcd9/Fu+iTdB3DiJd59ePHY9UYTEq/EW9K/qSYvuXl3NWw+HBEv8ZZ0D/H6s5ApBkasQ7zES7wlK0C8I4SYWpN4ibekdlINUHLzRg1GDakGsM56g/ultSQdL64tZcXj1u1PiVfiLenfVKOX3LzEK/GmGsA6656oS+pJOhLvEk48Zv3elHgl3pL+TTV7yc1LvBJvqgGss/6puqumpCPx7mLE5w/TlxKvxFvSv6mGL7l5iVfiTTWAdQ5zsp5WV9KRePVdvu96zSVeibekf1NCKLl5iVfiTTWAdfInL+lIvPou33cS78Rptz/5lT9SQlCDMeJJPb9V1zFqmFi+pOPwqSqmrV8X8RJvSf+mGq/k5s14zXhTDWCd/I98pCPx6rt835nxTpx2zXi92SXpjpEu8RJv2dCbkkLZArQLS9XAOnkBm/FOLF/SMWog3bx0Jd6JpWvUYNRAumOkS7zEWzb0pqRQtgBGDZsetRg1TCxf0jFqSB1w1nk0XRMv8Zb0b6pRS27efbybTrtGDRNL14zXjDd1uFnn8VmyxDuxfKU9owZSHPMCG/ESb0n/poRQcvNGDUYNqQawTv7kJR2JV9/l+86Md+K0a8Zrxku6Y6RLvMRbNvSmpFC2AO7j3fS4wYx3YvmSjlFD6oCzjvt4N32S7gM48RLvPrx47HqjCYlX4i3p31STl9y8uxo2H46Il3hLuod4/VnIFAMj1iFe4iXekhUg3hFCTK1JvMRbUjupBii5eaMGo4ZUA1hnvcH90lqSjhfXlrLicev2p8Qr8Zb0b6rRS25e4pV4Uw1gnXVP1CX1JB2JdwknHrN+b0q8Em9J/6aaveTmJV6JN9UA1ln/VN1VU9KReHcx4vOH6UuJV+It6d9Uw5fcvMQr8aYawDqHOVlPqyvpSLz6Lt93veYSr8Rb0r8pIZTcvMQr8aYawDr5k5d0JF59l+87iXfitNuf/MofKSGowRjxpJ7fqusYNUwsX9Jx+FQV09avi3iJt6R/U41XcvNmvGa8qQawTv5HPtKRePVdvu/MeCdOu2a83uySdMdIl3iJt2zoTUmhbAHahaVqYJ28gM14J5Yv6Rg1kG5euhLvxNI1ajBqIN0x0iVe4i0belNSKFsAo4ZNj1qMGiaWL+kYNaQOOOs8mq6Jl3hL+jfVqCU37z7eTaddo4aJpWvGa8abOtys8/gsWeKdWL7SnlEDKY55gY14ibekf1NCKLl5owajhlQDWCd/8pKOxKvv8n1nxjtx2jXjNeMl3THSJV7iLRt6U1IoWwD38W563GDGO7F8SceoIXXAWcd9vJs+SfcBnHiJdx9ePHa90YTEK/GW9G+qyUtu3l0Nmw9HxEu8Jd1DvP4sZIqBEesQL/ESb8kKEO8IIabWJF7iLamdVAOU3LxRg1FDqgGss97gfmktSceLa0tZ8bh1+1PilXhL+jfV6CU3L/FKvKkGsM66J+qSeh4dHZX0Tr+uJde/xmPUIM/dGs/bRf8eEu/EiffevXslxduvK9VYakC8KdYeXod4Jxbv7du3S4q3X1eqGdSAeFOsEe/Esv0lZJ9++mkp+fbrSTeCGpBvmjmJl4SP33nnneNvvvnm+Oeffx4m4b5+v450AzxYTw3IN8ke8RLvMNklQbcWsVZigHiJl3gxgIEwA8QbLnilU9e1SIEYGMMA8RKvtIMBDIQZIN5wwSWMMQlD3dW9EgPES7zSDgYwEGaAeMMFr3TquhYpEANjGCBe4pV2MICBMAPEGy64hDEmYai7uldigHiJV9rBAAbCDBBvuOCVTl3XIgViYAwDxEu80g4GMBBmgHjDBZcwxiQMdVf3SgwQL/FKOxjAQJgB4g0XvNKp61qkQAyMYYB4iVfawQAGwgwQb7jgEsaYhKHu6l6JAeIlXmkHAxgIM0C84YJXOnVdixSIgTEMEC/xSjsYwECYAeINF1zCGJMw1F3dKzFAvMQr7WAAA2EGiDdc8EqnrmuRAjEwhgHiJV5pBwMYCDNAvOGCSxhjEoa6q3slBoiXeKUdDGAgzADxhgte6dR1LVIgBsYwQLzEK+1gAANhBog3XHAJY0zCUHd1r8QA8RKvtIMBDIQZIN5wwSuduq5FCsTAGAaIl3ilHQxgIMwA8YYLLmGMSRjqru6VGCBe4pV2MICBMAPEGy54pVPXtUiBGBjDAPESr7SDAQyEGSDecMEljDEJQ93VvRIDxEu80g4GMBBmgHjDBa906roWKRADYxggXuKVdjCAgTADxBsuuIQxJmGou7pXYoB4iVfawQAGwgwQb7jglU5d1yIFYmAMA8RLvNIOBjAQZoB4wwWXMMYkDHVX90oMEC/xSjsYwECYAeINF7zSqetapEAMjGGAeIlX2sEABsIMEG+44BLGmISh7upeiQHiJV5pBwMYCDNAvOGCVzp1XYsUiIExDBAv8Uo7GMBAmAHiDRdcwhiTMNRd3SsxQLzEK+1gAANhBog3XPBKp65rkQIxMIYB4iVeaQcDGAgzQLzhgksYYxKGuqt7JQaIl3ilHQxgIMvA0anivXr16g+VTgnXIrVgAAMXnYHm1f/sSrzfXvRNun6NigEMVGKgifffuxLv55Uu2LVoIAxg4KIz0MT7+a7E++FF36Tr16gYwEAxBj7clXjfLHbBXgTIvgig3uqNgZUZaIn3r6eK9/r16y8Sr7SAAQxgYD0GuldPFe+lS5eeagX/UdHXK7paqiUGpmbgqHv1VPH2TzZI7gJlalD8qLnyj5r6aep+urtTuifivQWUqUEhXuLFwHoM3Fok3jYIfraJ9z75ki8GMICBczFwv/t0kXj7g9qD/6ng5yq4xLBeYlBLtbyQDDSPfrxYuv2Br7766p+Jl3gxgAEMnJ2BJt4X9hKvF9nOXmygqh0GMNBvUthbuifjhucBBCAMYAAD+zPQ0u7zZxLviXw/UPT9i65maoaBeRlo0v3gzNLtX3jlypXn2jf5HkTzQuS599xjYDkD3Zfdm+cS78kLbS8r/PLCq5VaYWBeBtqNCS+fW7oPvkGz+Ntgmhcmz73nHgO7GeieXE26/Rtdvnz5yVb4O4q/u/hqpEYYmJKBO92Tq4q3f7ObN28+3YD6F6imhOpC3sCOVayGGPiy+3F16T40cui/TvxlaDOa3W8sYQAD1Rn4cq9fCz6rnV977bXfNfF+Rr7SBAYwMDkDn3UfntWle3/dycz33cmLXv0kdn3SIgYOx8C7B5npLrFxi9iXvCW81OMAxsAsDHTfde8t8eNBH9Pe1uKZk9vNjmYpvn0SDQamY+Coe6777qBC3febtwv6Q/9VOUBOB6QfZw/346zaFqht91r3275OjD7+xo0bf+p/h5KACRgDGLjIDHSPdZ9FBXrexU7eyeL1kzsgvKNFgZP7IjeBayfxAAPdU/2Ordcjt4idV7K7vr6/y2Z/i+O2mTfapv7W/vtF++9XgUL6UY3wMYCBX2PgqxMPdR+90f206N2Ad8nO51VABVRABVRABVRABVRABVRABVRABVRABVRABVRABTZfgf8CGR0eAYmNuzMAAAAASUVORK5CYII=\");}\n.#<uispace> .js-loading{background-image:url(\"data:image/png;base64,R0lGODlhGgAaAOZTAPz8/PLy8u3t7fDw8PX19fn5+fr6+v39/ff399ra2vj4+LS0tPv7+4+Pj2lpaf7+/vT09O/v7+7u7sHBweDg4OXl5erq6pWVlfPz85CQkOTk5Lm5ucrKytzc3KOjo7GxsXJycq2trdbW1t3d3cnJyejo6Obm5tTU1KysrJaWltDQ0MfHx4WFhbCwsGpqauPj49/f39fX1+vr65KSkqqqqmtra7+/v/b29tLS0np6eqKiooSEhJGRkcDAwJubm7W1tdXV1a6urs/Pz7y8vOLi4pSUlKurq9vb23FxccTExMjIyIODg6WlpYeHh8PDw9HR0eHh4fHx8ezs7P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpENjdBNEJEODc5RDNFMDExQUU0NkQ5MkQ0QkJCOTZDQSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoyMkZEQjVEQ0U4RDMxMUUwQjI1NUZDMjA5MkZGQ0VFRiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyMkZEQjVEQkU4RDMxMUUwQjI1NUZDMjA5MkZGQ0VFRiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5NzY0Rjk1OUNDRThFMDExQkQyOThDMjVCRjJEQTlBMiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpENjdBNEJEODc5RDNFMDExQUU0NkQ5MkQ0QkJCOTZDQSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgH//v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/e3dzb2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vLu6ubi3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZmJeWlZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1dHNycXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1JRUE9OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy4tLCsqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MCwoJCAcGBQQDAgEAACH5BAUKAFMALAAAAAAaABoAAAf/gFOCgwcwg1MXGYcGh42HHx4Cgy4OgwADAY6OEw1BDIKUg1FSBJqNUYlHgiCVUwVSAgemjSoNHghTrFMPA1K4piWLHg0qiIoIUgONBQWDC0qZgkQ+SYcEEoyCDKPKghsLC0CfUxSO2VMEUrAKgwwn4BMK7KYHEeoQmgEcJBgYswBRAgCYNSUawYEEExKs0KFDggQVFAoKIECAugAvHj58IXHKKHVSonQcOYgZSUfbkhE0aSrdOoK9oowjZE8KPkHnBjFSYJHUIYACLWE6FGAAQgjqIsgShFCUzwAi04lkCrXpMliy1E05YLGZJVO8fAnSOgXZgAcKzQ6yOKjXL4LXDc6xxSmhlMKcUBdpCgQAIfkECQoAUwAsAAAAABQADgAAB4aAU4KDDxaDUy0ohycAh4IcExiDGQ2DJjspjlMiCySNU5SCBkUOIZo3Gz8lgheVU0I1IAKaUzALEwVTrVMQLA49gxCHABMLFIiKEw4sCoMJGs2CMkMxhx851YMdCQkWB4KGjiKOBxbcFAwMtOsKFdDR67Tw8fT1AQICUlIB9YNR+vqi9BMUCAAh+QQJCgBTACwAAAAAGgAaAAAHtIBTgoNTBIQcK4QwB4SNgxUUBYMLC4MCHh+OjhYJGg+ClIIMQQ0Tmo0MHQkYghuVU0cZF1GnjQMJFABTrlMIHg0qtZKDDxQJA1OIUyoNHgaEOE+DUlEMgwQjMoRJPkSDGjwOTZZSUoaC54QUggpGDg5IJIQQ5REHjKcDS+80Co4AAaIA0HXKxIwUFWpNIagwocKHCgMIEFAuAMRTUcqVo3Wxo8ePIEOKHEmypMmTKFOqXDkoEAAh+QQJCgBTACwAAAAAGgAaAAAH/4BTgoNTBoQVL4QWD4SNgwEDAIMJCYMYExyOjgRSUZOVUwAkCyKajQcCUgWCHaAlPxs3po0IUgOMrVMFEwsws6uEA1IIU4hTFAsTkoMjI4OdDIMGEgSEMUMygxYhDUyDqVLVgoaNFoK7DQ0XpYMQUlIRBwezGDrpNsCEAAFRAMuaUkJ8kDIrVEFBBA8qNBVAALgAC6dcAAHChYsLUd6987Qwg4OPDjJEHDmoQD6SgxhkHFDQ5CxOUgQoKCgsSjRCByK8gyDNkSEF4MQJAhAlwD8AAyA+iiTIHbx5QxtlrMZvCieOofj9a1Qg5rx3U1Cp0mfqgTBiU8BOqXVLIdtvCRSnnFVIQAK5KamkUVt4d0rVno4CAQAh+QQJCgBTACwAAAAAGgAaAAAH/4BTgoNTBoQBUYQEhIyHAwCDUlKDBRQVjY0EUomCkoIPGgkWmIwHAlIFgqeCGAkdDKSMCFIDD1OrABQJA7GphANSCFOIUwMJFLaDJSWRUbCCBhKLgzIj08NKC06Dp1LXhozTDEALCxsahBCSEQcHsQoT5SfPhACIAJCkGCQcAbFT+f75+0dQoIBuAwu2uHAhQ4YWUSRJ4lQQRYOLDVAU3IipgC+OjRhE5BXrCY5YmqQIUPCviQMe6AgdiCAJwiBwhAyRQOLAgRGWggBECRAQwICEwx5NUUCj5xKSABlFXERME8UKKWaYIFVApTtPplARuoTpATBhUzxNmVWrIFtukxMEnS1IQALOVdCkbcQ5jGIhTIEAACH5BAkKAFMALAAAAAAaABoAAAf/gFOCg1MGhAFRhIaEjIMBAwCDUlKDAAMBjY0EUomCk4NRUgSZjAcCUgWCp4IFUgIHpIwIUgMPU6sPA1IIsamEuryIU7MDjBAYklEMgwYSo4MEEotTChoJUIOnosyNiwcWCQkdnYIQkxEHsKQMFOEW6oQAiACRpNUVCrFT9fr5+v/6AgjQhgngFA4bNixYwCHUJE4Gp6xYuHBFxIuDCvjCSIhBqGKxRoyItcmVP1JMGoSwUCrCJAjc4p2YIuJCgwYTNgKIEoCfpYKCUuwwMaWAjZs6kAniJyjUKGEhHBRZJOVDCEqZWr2a8kkAiBpCCGFtlGuXJ6w9HLCA+Y9YNqwKFlg4mAAw2rRVgmLk+GBw2hRhg0RkCgQAIfkEBQoAUwAsAAAAABoAGgAAB/+AU4KDUwaEAVGEhoSMgwEDAINSUoMAAwGNjQRSiYKTg1FSBJmMBwJSBYKnggVSAgekjAhSAw9Tqw8DUgixqYS6vIhTswOMBb5TnAyDBhKjgwQSi1MMocWqk8+FjdObrgqEEJMRB7CkBxGTEJkAiACRpABRAfDxsZX3+fkBAqdSmPqmVOjQIUGCCqEmcQo45YVBgy8YShx0bGKjarTulSgRy5sAcLGcLFACcBA6dcxKwZiiYcOCBUCWCZJHr9IlQh88CKB24uUEkFPqCQo16kKGKRMaBJEZgAMJDKRavZriwsGUKEaPHCKVa5egqoJUNPDAKx+xQSCsFvLQQIW+aNMP0g4i4iNJwGlTjBKikCkQACH5BAkKAFMALAYADAAUAA4AAAeHgFOCg4SEAQICUlIBhY2DUYqKUY6UlZaXjhgQmI1QCRoKjicAhA8WU1EdCQkWB4QmOymEHBMYUwcWqxQMggZFDiFTLShTIgskpFMKFaCCQjUgAlMZDVM3Gz8lhKFTECwOPYLUgjALEwWNEw4s3BfVUwATCxSNHzkxg+6DMkP4jSKEhhE61SgQACH5BAkKAFMALAAAAAAaABoAAAezgFOCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXmJmHAQICUlIBlFGfn1GahjhPlho8Dk2KBQWICkYODkgkigNSUQyFA0u2NAqCMAeFBFMKnlLJgyYzKRWDAh4fhBUUslMQnxHHgtODDEENE1McK1MWCRoPggABUQCIRxkXpgsLUwwdCRiE6B1C4KGBCkH6BA1IQEGgIhUNPBgQtGHflAcUEgxglMQHkUEVBxEYIaMRBULpCDkrFAgAIfkECQoAUwAsAAAAABoAGgAAB/+AU4KDUwaEAVGEhoSMgwEDAINSUoMAAwGNjQRSiYKTg1FSBJmMBwJSBYKnggVSAgekjAhSAw9Tqw8DUgixqYS6vIhTswOMBb5TnAyDBhKjgwQSi1MMocWqk8+FjdObrgqEEJMRB7CkBxGTEJkAiACRpABRAfDxsZX3+fkXICAuLhf0CQog4JSUABkcKHSQQeCUUJM4OZw4aMQIio0shGjA5N4xUgUmNGhwQcQ9XVGWEcKgY6QNXxZsKZqiwKC2ZCE+UBKEYQKHQ5AEiZNCThIhACQWmKzwYsqmTlPaRanHqMSPDTemJEgwxRSqoyAnLIAhaKsgYjLvUVgwAV4HroITgOmLMUTGoLfMnAm0QIjpzEaBAAAh+QQJCgBTACwAAAAAGgAaAAAH/4BTgoNTBoQBUYSGhIyDAQMAg1JSgwADAY2NBFKJgpODUVIEmYwHAlIFgqeCBVICB6SMCFIDD1OrDwNSCLE4jLq8iFOzA4wFqYIOPBqDBhKjgwQSi1MMocWCSA4ORgqC1M3RkwLeggo020sD2JkHEZMQmRUpMyYmsQBRAZGxFbGV/wIGbHHhQoYMLQQKCiDglJQAKBpIbIBC4ZRQkzhZ3DioRAmOjQIoWeDk3zFSDIAsWLCBWSxdURgwUjBh5QmZU6ApmqLAoc4pGEhwwMSKgj9HkARBmBQB1kJCDzQksDBF2KZOUwAg4tcIQ4IOMj+ZQkWIKyMAFBJg+zSMlq2AAxYSUHi7ShAwgTJG6Kxb6JnCn8LCNQoEACH5BAUKAFMALAAAAAAaABoAAAf/gFOCgwAng1MBUYcGh42HKTsmg1JShAMBjo4hDkWMU5SDUVIEmY0CIDVCggKVUwVSAgeljT0OLBBTrFMPA1IIsyOHCiwOE4iKCFIDjQUFgw0hFoMxOR+HBBKeUwyiy4IXDQ0TzlMijtoElAIKgwU24ToYGLMHEZS4jlIfIaClAFEBAMz6NFCQwIIIS3HYsGHBAg4JEQlgJSXACocOV0QURUmKooggBUGYF7KRAg0JoAxsVuqAhQQJOnws1SsKg0YMKMC0IGuKtkGMFFAkNehkBXYGLx0KMOAgBEoRek5BGmrUsSnpZgJIdNDRq1ifKh1gRc5gKV6+BPVLNuABQraDFHQJ6vWrIDZtcn1KIFrwZ6JFmQIBADs=\")}"
  },
  {
    "path": "src/ui/audio/audio.html",
    "content": "<div>\n\t<marquee class=\"z-ttl\"></marquee>\n\t<div class=\"z-act js-play\">&nbsp;</div>\n</div>"
  },
  {
    "path": "src/ui/audio/audio.js",
    "content": "/*\n * ------------------------------------------\n * 音频播放器实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/audio/audio */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'ui/base',\n    'util/media/audio',\n    'util/template/tpl',\n    'text!./audio.css',\n    'text!./audio.html'\n],function(NEJ,_k,_e,_v,_u,_t0,_t1,_css,_html,_p,_o,_f,_r){\n    // variable declaration\n    var _pro,\n        _seed_css = _e._$pushCSSText(_css),\n        _seed_html= _t1._$addNodeTemplate(_html);\n    /**\n     * 音频播放器\n     *\n     * @class   module:ui/audio/audio._$$AudioPlayer\n     * @uses    module:util/audio/audio._$$MediaAudio\n     * @extends module:ui/base._$$Abstract\n     * @param     {Object}  config    - 可选配置参数\n     * @property  {String}  url       - 音乐地址\n     * @property  {String}  title     - 音乐标题\n     * @property  {Boolean} autostart - 自动开始播放\n     */\n    /**\n     * 状态变化事件\n     *\n     * @event  module:ui/audio/audio._$$AudioPlayer#onstatechange\n     * @param  {Object} arg0 - 事件对象\n     */\n    _p._$$AudioPlayer = _k._$klass();\n    _pro = _p._$$AudioPlayer._$extend(_u._$$Abstract);\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/audio/audio._$$AudioPlayer#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css = _seed_css;\n        this.__seed_html= _seed_html;\n    };\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method ui/audio/audio._$$AudioPlayer#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        var _child = _e._$getChildren(this.__body);\n        this.__nttl = _child[0];\n        this.__nact = _child[1];\n        _v._$addEvent(this.__nact,'tap',\n                     this.__onAction._$bind(this));\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method ui/audio/audio._$$AudioPlayer#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__nttl.innerHTML = _options.title||'音乐标题';\n        this.__audio = this.__getAudio(_options.url);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method ui/audio/audio._$$AudioPlayer#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        if (!!this.__audio)\n            this.__audio = this.__audio.constructor\n                               ._$recycle(this.__audio);\n    };\n    /**\n     * 操作事件\n     *\n     * @protected\n     * @method ui/audio/audio._$$AudioPlayer#__onAction\n     * @return {Void}\n     */\n    _pro.__onAction = function(){\n        _e._$hasClassName(this.__nact,'js-play')?this._$play():this._$pause();\n    };\n    /**\n     * 返回音频对象\n     *\n     * @protected\n     * @method ui/audio/audio._$$AudioPlayer#__getAudio\n     * @param  {String} arg0 - 音频URI\n     * @return {Object} 音频对象\n     */\n    _pro.__getAudio = function(_source){\n        return _t0._$$MediaAudio._$allocate({url:_source,\n               onstatechange:this.__onStateChange._$bind(this)});\n    };\n    /**\n     * 音频控件状态变化回调事件\n     *\n     * @protected\n     * @method ui/audio/audio._$$AudioPlayer#__onStateChange\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onStateChange = (function(){\n        var _state_list = ['js-play','js-loading','js-pause'],\n            _state_str  = _state_list.join(' ');\n        return function(_event){\n            this.__state = _event.state;\n            _e._$replaceClassName(this.__nact,_state_str,\n              _state_list[_event.state]||_state_list[0]);\n            this._$dispatchEvent('onstatechange',_event);\n        };\n    })();\n    /**\n     * 播放音乐\n     * @method ui/audio/audio._$$AudioPlayer#_$play\n     * @return {Void}\n     */\n    _pro._$play = function(){\n        if (!!this.__audio)\n            this.__audio._$play();\n    };\n    /**\n     * 暂停播放\n     *\n     * @method ui/audio/audio._$$AudioPlayer#_$pause\n     * @return {Void}\n     */\n    _pro._$pause = function(){\n        if (!!this.__audio)\n            this.__audio._$pause();\n    };\n    /**\n     * 停止播放\n     *\n     * @method ui/audio/audio._$$AudioPlayer#_$stop\n     * @return {Void}\n     */\n    _pro._$stop = function(){\n        if (!!this.__audio)\n            this.__audio._$stop();\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/audio/mp3.css",
    "content": ".#<uispace> .m-pre, .#<uispace> .m-play, .#<uispace> .m-next, .#<uispace> .m-cur, .#<uispace> .m-pause, .#<uispace> .m-volmin,\n.#<uispace> .m-volminc, .#<uispace> .m-shuffled, .#<uispace> .m-repeatd-1, .#<uispace> .m-shufflec, .#<uispace> .m-repeatd, .#<uispace> .m-repeatc,\n.#<uispace> .m-volmax, .#<uispace> .m-volmaxc{background:url(#<root>audio_sprite.png) no-repeat 9999px 9999px;}\n.#<uispace> .m-player{height:40px;min-width:530px;background:#606060;cursor:default}\n.#<uispace> .m-player .ctl{width:300px; float:left;}\n.#<uispace> .m-pre{height:10px;width:16px;background-position:0 0;float:left;margin-top:14px;margin-left: 10px;}\n.#<uispace> .m-pre:active, .#<uispace> .m-preatv{background-position:-104px -1px;}\n.#<uispace> .m-play{height:11px;width:10px;background-position:2px -28px;float:left;margin:14px 20px 0;}\n.#<uispace> .m-play:active{background-position:-202px -36px;}\n.#<uispace> .m-pause{height:11px;width:10px;background-position:0 -96px;float:left;margin:14px 20px 0;}\n.#<uispace> .m-pause:active{background-position:-155px -36px;}\n.#<uispace> .m-next{height:10px;width:16px;background-position:0 -61px;float:left;margin-top:14px;}\n.#<uispace> .m-next:active, .#<uispace>  .m-nextatv{background-position:-103px -81px;}\n.#<uispace> .m-player .loop{width:120px;float:right}\n.#<uispace> .m-curtime{float: right;margin-right: 10px;color:#fff;line-height: 40px;}\n.#<uispace> .m-time{float: left;margin-left: 10px;color:#fff;line-height: 40px;}\n.#<uispace> .m-player .timeline{height:25px;position:absolute;left:315px;right:120px;bottom:0;top:0;width:135px;padding-top:15px;}\n.#<uispace> .m-vol{height:27px;width:90px;padding:13px 0 0 20px;float:left;}\n.#<uispace> .m-volicn{width:20px;height:20px;margin:10px 0 0 10px;float:left}\n.#<uispace> .m-vzero .m-volminc{background-position:0 -354px;width:100%;height:100%;float:left;}\n.#<uispace> .m-vmin .m-volminc{background-position:0 -124px;width:100%;height:100%;float:left;}\n.#<uispace> .m-vmax .m-volminc{background-position:0 -155px;width:100%;height:100%;float:left;}\n.#<uispace> .m-timeline{position:absolute;width:100%;height:8px;border-radius:4px;background:#3b3b3b;border-top:1px solid #212121;border-bottom:1px solid #636363}\n.#<uispace> .m-timelinei{width:0%;}\n.#<uispace> .m-timeline-1{margin-top:0px;width:90px;position:absolute;}\n.#<uispace> .m-progress{background:green;margin-top:-1px;}\n.#<uispace> .m-cur{position:absolute;right:-5px;margin-left:-5px;background-position:0 -302px;height:10px;width:10px;}\n.#<uispace> .m-cur2{position:absolute;right:-5px;margin-left:-5px;background:url(#<root>audio_sprite.png) no-repeat 9999px 9999px;width:10px;background-position:0 -302px;}\n.#<uispace> .m-cur:active, .#<uispace> .m-cur2:active{background-position:0 -328px;}\n.#<uispace> .m-shuffled{background-position:0 -262px;}\n.#<uispace> .m-shufflec{background-position:-56px -115px;}\n.#<uispace> .m-repeatb, .m-repeatb-1, .m-shuffleb{height:22px;width:32px;float:right;margin:10px 10px 0 0 }\n.#<uispace> .m-repeatd{background-position:0 -187px;}\n.#<uispace> .m-repeatd-1{background-position:0 -225px;}\n.#<uispace> .m-repeatc{background-position:-56px -149px;}\n.m-cnt{width:600px;position: relative;}"
  },
  {
    "path": "src/ui/audio/mp3.html",
    "content": "<div class=\"m-cnt\">\n\t<div class=\"cse\">\n\t  <div class=\"m-player\">\n\t    <div class=\"ctl\">\n\t      <span class=\"f-ib m-pre\" data-name=\"pre\">&nbsp;</span>\n\t      <span class=\"f-ib m-play ztag\" data-name=\"play\">&nbsp;</span>\n\t      <span class=\"f-ib m-next\" data-name=\"next\" value=\"next\">&nbsp;</span>\n\t      <div class=\"m-vol\">\n\t        <div class=\"f-ib m-timeline m-timeline-1 vtag\">\n\t          <div class=\"f-ib m-timeline m-progress m-timeline-1 vtag\">\n\t            <span class=\"f-ib m-cur2 vtag\">&nbsp;</span>\n\t          </div>\n\t        </div>\n\t      </div>\n\t      <span class=\"m-volicn ztag m-vmax f-ib\">\n\t        <span class=\"f-ib m-volminc\">&nbsp;</span>\n\t      </span>\n\t      <span class=\"m-curtime ztag\">00:00</span>\n\t    </div>\n\t    <div class=\"timeline\">\n\t      <div class=\"m-timeline ttag\">\n\t        <div class=\"m-timeline m-progress ttag m-timelinei\">\n\t          <span class=\"m-cur ttag\">&nbsp;</span>\n\t        </div>\n\t      </div>\n\t    </div>\n\t    <div class=\"loop\">\n\t      <span class=\"m-time ztag\">00:00</span>\n\t      <span class=\"m-repeatb m-repeatd ztag\" data-name=\"mode\">&nbsp;</span>\n\t    </div>\n\t  </div>\n\t</div>\n</div>"
  },
  {
    "path": "src/ui/audio/mp3.js",
    "content": "/*\n * ------------------------------------------\n * 音频播放器实现文件\n * @version  1.0\n * @author   cheng-lin(cheng-lin@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/audio/mp3 */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'ui/base',\n    'base/config',\n    'util/slider/slider.simple',\n    'util/media/playlist',\n    'util/audio/audio',\n    'util/template/tpl',\n    'text!./mp3.css',\n    'text!./mp3.html'\n],function(NEJ,_k,_e,_v,_u,_c,_t0,_t1,_t2,_t3,_css,_html,_p,_o,_f,_r) {\n    var _pro,\n        _seed_css = _e._$pushCSSText(_css,{root:_c._$get('root')}),\n        _seed_html= _t3._$addNodeTemplate(_html);\n    /**\n     * 音频播放器\n     *\n     * @class     module:ui/audio/mp3._$$MP3Player\n     * @uses      module:util/slider/simple._$$SimpleSlider\n     * @uses      module:util/media/playlist._$$PlayList\n     * @extends   module:ui/base._$$Abstract\n     * @param     {Object}      config     - 可选配置参数\n     * @property  {String|Node} parent     - 父节点\n     * @property  {String}      mode       - 播放模式，0:列表(默认)，1:单曲，2:随机\n     * @property  {Array}       list       - 歌曲列表\n     * @property  {Boolean}     autostart  - 是否自动开始，0:不自动，1:自动(默认)\n     */\n    _p._$$MP3Player = _k._$klass();\n    _pro = _p._$$MP3Player._$extend(_u._$$Abstract);\n\n    /**\n     * 重置控件\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__reset\n     * @param  {Objec} _options - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__vslide.value = _options.volnumber||100;\n        this.__autostart = _options.autostart === 0 ? !1 : !0;\n        this.__doInitDomEvent([\n            [this.__body,'click',this.__onAction._$bind(this)]\n        ]);\n        if (!this.__volSlider){\n            this.__volSlider = _t0._$$SimpleSlider._$allocate(this.__vslide);\n        }\n        this._$refreshList(_options);\n    };\n\n    /**\n     * 销毁控件\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__doClearComponent();\n        this.__super();\n    };\n\n    /**\n     * 初始化播放器结构\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css = _seed_css;\n        this.__seed_html = _seed_html;\n    };\n\n    /**\n     * 初始化结构\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        // 0 - 播放按钮\n        // 1 - 小音量\n        // 2 - 当前播放时间\n        // 3 - 歌曲总时长\n        // 4 - 歌曲播放模式\n        var _list  = _e._$getByClassName(this.__body,'ztag'),\n            _vlist = _e._$getByClassName(this.__body,'vtag'),\n            _tlist = _e._$getByClassName(this.__body,'ttag');\n        this.__nplay  = _list[0];\n        this.__nvol   = _list[1];\n        this.__nctime = _list[2];\n        this.__nstime = _list[3];\n        this.__nmode  = _list[4];\n        this.__vslide = {\n            track:_vlist[0],\n            thumb:_vlist[2],\n            progress:_vlist[1],\n            onslidestop:this.__onVolSlideStop._$bind(this)\n        };\n        this.__tslide = {\n            track:_tlist[0],\n            thumb:_tlist[2],\n            progress:_tlist[1],\n            value:0,\n            onslidestop:this.__onTimeSlideStop._$bind(this)\n        };\n    };\n\n    /**\n     * 播放器点击事件\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__onAction\n     * @param  {Event} _event - 事件对象\n     * @return {Void}\n     */\n    _pro.__onAction = function(_event){\n        var _action;\n        var _node = _v._$getElement(_event,function(_node){\n            _action = _e._$dataset(_node,'name');\n            return !!_action;\n        });\n        if (!_node) return;\n        if (_action == 'mode'){\n            this.__doModeChange();\n        }\n        if (!this.__audio) return;\n        this.__autostart = !0;\n        if (_action == 'pre'){\n            this.__onPre();\n        }else if (_action == 'play'){\n            this.__onPlay();\n        }else if (_action == 'next'){\n            this.__onNext();\n        }\n    };\n\n    /**\n     * 更新音量大小图标\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__onVolumeChange\n     * @return {Void}\n     */\n    _pro.__onVolumeChange = (function(){\n        var _map = ['m-vmax','m-vmin','m-vzero'],\n            _old = _map.join(' ');\n        return function(_event){\n            this.__volSlider._$setPosition(_event.volume/this.__vslide.value);\n            var _value = _event.volume;\n            if (_value == 0){\n                _value = 2;\n            }else if (_value < 50){\n                _value = 1;\n            }else{\n                _value = 0;\n            }\n            _e._$replaceClassName(this.__nvol,_old,_map[_value]);\n        };\n    })();\n\n    /**\n     * 播放模式切换\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__doModeChange\n     * @param  {Event} _event - 事件对象\n     * @return {Void}\n     */\n    _pro.__doModeChange = function(_event){\n        var _mode = this.__playlist._$getPlayMode();\n        this.__playlist._$setPlayMode((_mode+1)%3);\n    };\n\n    /**\n     * 切换前一首\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__onPre\n     * @return {Void}\n     */\n    _pro.__onPre = function(){\n        this.__playlist._$prev();\n    };\n\n    /**\n     * 播放或暂停\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__onPlay\n     * @param  {Event} _event - 事件对象\n     * @return {Void}\n     */\n    _pro.__onPlay = function(_event){\n        if (!!this.__audio){\n            var _pause = _e._$hasClassName(this.__nplay,'m-play');\n            if (_pause){\n                this.__audio._$play();\n            }else{\n                this.__audio._$pause();\n            }\n        }else{\n            this.__playlist._$play();\n        }\n    };\n\n    /**\n     * 切换下一首\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__onNext\n     * @return {Void}\n     */\n    _pro.__onNext = function(){\n        this.__playlist._$next();\n    };\n\n    /**\n     * 播放状态更新\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__onStateChange\n     * @param  {Event} _event - 事件对象\n     * @return {Void}\n     */\n    _pro.__onStateChange = function(_event){\n        var _state = _event.state;\n        if (_state == 2){\n            _e._$replaceClassName(this.__nplay,'m-play','m-pause');\n        }else{\n            _e._$replaceClassName(this.__nplay,'m-pause','m-play');\n        }\n        if (_state == 0 || _state == 4){\n            this.__onTimeUpdate({current:0,duration:0});\n        }\n        if (_state == 4){\n            this.__playlist._$autoNext();\n        }\n    };\n\n    /**\n     * 更新时间轴\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__onTimeUpdate\n     * @param  {Event} _event - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTimeUpdate = function(_event){\n        if (!this.__timeSlider)\n            this.__timeSlider = _t0._$$SimpleSlider._$allocate(this.__tslide);\n        // 播放第二首的current有问题\n        var _current  = _event.current,\n            _duration = _event.duration;\n        if (parseInt(_current) === 0){\n            this.__nctime.innerHTML = '00:00';\n            this.__nstime.innerHTML = this.__doFormatSecond(_duration);\n        }\n        this.__nctime.innerHTML = this.__doFormatSecond(_current);\n        var _played = _current / (_duration ? _duration : 1);\n        this.__timeSlider._$setPosition(_played);\n    };\n\n    /**\n     * 格式化秒为小时或分钟\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__doFormatSecond\n     * @param  {Number}  _second - 秒数\n     * @return {String}  格式化好的时间\n     */\n    _pro.__doFormatSecond = function(_second){\n        var _hour = parseInt(_second/3600),\n            _min  = parseInt((_second%3600)/60),\n            _sec  = parseInt(_second%60);\n            _min = _min > 9 ? _min : '0' + _min;\n            _sec = _sec > 9 ? _sec : '0' + _sec;\n        return (_hour > 0 ?  _hour + ':' : '') + _min + ':' +  _sec;\n    };\n\n    /**\n     * 设置播放时间\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__onTimeSlideStop\n     * @param  {Event} _event - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTimeSlideStop = function(_event){\n        if (!this.__audio._$duration()) return;\n        var _value = _event.ratio;\n        this.__audio._$seek(_value * this.__audio._$duration());\n    };\n\n    /**\n     * 设置音量\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__onVolSlideStop\n     * @param  {Event} _event - 事件对象\n     * @return {Void}\n     */\n    _pro.__onVolSlideStop = function(_event){\n        var _value = _event.ratio;\n            _value = _value * this.__vslide.value\n        if (!!this.__audio){\n            this.__audio._$volume(_value);\n        }else{\n            this.__onVolumeChange({volume:_value});\n        }\n    };\n\n    /**\n     * 更新播放模式\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__onModeChange\n     * @param  {Event} _event - 事件对象\n     * @return {Void}\n     */\n    _pro.__onModeChange = (function(){\n        var _map = ['m-repeatb m-repeatd','m-repeatb-1 m-repeatd-1','m-shuffleb m-shuffled'],\n            _old = _map.join(' ');\n        return function(_event){\n            _e._$replaceClassName(this.__nmode,_old,_map[_event.mode]);\n        };\n    })();\n\n    /**\n     * 多媒体状态改变\n     *\n     * @protected\n     * @method ui/audio/mp3._$$MP3Player#__onMediaChange\n     * @param  {Object} _options - 配置信息\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onMediaChange = function(_options,_event){\n        if (_event.index < 0){\n            if (!!this.__audio){\n                this.__audio = this.__audio._$recycle();\n            }\n            this.__onTimeUpdate({current:0,duration:0});\n            this.__onStateChange({state:0});\n            if (!!this.__timeSlider){\n                this.__timeSlider = this.__timeSlider._$recycle();\n            }\n            return;\n        }\n        var _url = _event.list[_event.index];\n        if (!this.__audio){\n            var _volume = this.__volSlider._$getPosition() * this.__vslide.value;\n            this.__audio =  _t2._$audio({\n                preload:_options.preload||false,\n                volume:_volume,\n                onstatechange:this.__onStateChange._$bind(this),\n                ontimeupdate:this.__onTimeUpdate._$bind(this),\n                onvolumechange:this.__onVolumeChange._$bind(this)\n            });\n        }\n        this.__audio._$source(_url);\n        if (this.__autostart){\n            setTimeout(function(){\n                this.__audio._$play();\n            }._$bind(this),0);\n        }\n    };\n\n    /**\n     * 指定播放歌曲\n     *\n     * @method ui/audio/mp3._$$MP3Player#_$playByIndex\n     * @param  {Number} arg0 -  歌曲列表的下标，默认为0\n     * @return {Void}\n     */\n    _pro._$playByIndex = function(_index){\n        _index = _index || 0;\n        this.__autostart = !0;\n        this.__playlist._$setPlayIndex(_index);\n    };\n\n    /**\n     * 开始播放\n     *\n     * @method ui/audio/mp3._$$MP3Player#_$play\n     * @return {Void}\n     */\n    _pro._$play = function(){\n        this.__autostart = !0;\n        this.__playlist._$play();\n    };\n\n    /**\n     * 刷新播放列表\n     *\n     * @method ui/audio/mp3._$$MP3Player#_$refreshList\n     * @param    {Object} arg0 - 配置信息\n     * @property {Array}  mode - 歌曲播放模式\n     * @property {Array}  list - 歌曲列表\n     * @return   {Void}\n     */\n    _pro._$refreshList = function(_options){\n        var _mode = _options.mode||0,\n            _list = _options.list||[];\n        if (!this.__playlist){\n            this.__playlist = _t1._$$PlayList._$allocate({\n                mode:_mode,\n                list:_list,\n                onmodechange:this.__onModeChange._$bind(this),\n                onmediachange:this.__onMediaChange._$bind(this,_options)\n            });\n        }else{\n            this.__autostart = !0;\n            this.__playlist._$setPlayMode(_mode);\n            this.__playlist._$setPlayList(_list);\n        }\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/audio/test/audio.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>audio测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style type=\"text/css\">\n\t\t\tdiv{-webkit-user-select:none;}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit audio test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<div id=\"id-box\"></div>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./audio.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/ui/audio/test/audio.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"audio\");\n    //开始单元测试\n    test('audio',function(){\n        expect(0);\n        var _audio = nej.ui._$$AudioPlayer._$allocate({\n            parent:document.getElementById('id-box'),\n            title:'Track01',\n            url:'http://www.zhlongyin.com/UploadFiles/xrxz/2011/5/201105051307513619.mp3',\n\t\t\tonstatechange:function(_event){\n\t\t\t}\n        });\n        setTimeout(function(){\n            _audio._$play();\n        },500);\n//        _audio._$pause();\n//        _audio._$stop();\n//        _audio._$play();\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}audio.test.js',['ui/audio/audio'],f);\n});"
  },
  {
    "path": "src/ui/audio/test/mp3.test.html",
    "content": "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<title>mp3测试页</title>\n\t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit mask test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<div id=\"box\" class=\"box\"></div>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./mp3.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/ui/audio/test/mp3.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"ui-mp3\");\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _p = _('nej.ui');\n\n    //开始单元测试\n    test('mp3',function(){\n    \texpect(0);\n        // var _mp3 = _p._$$MP3Player._$allocate({\n        //     parent:'box',\n        //     list:[]\n        // });\n\n        // _mp3 = _p._$$MP3Player._$recycle(_mp3);\n        var _mp3 = _p._$$MP3Player._$allocate({\n            parent:'box',\n            mode:1,\n            list:['http://www.zhlongyin.com/UploadFiles/xrxz/2011/5/201105051307513619.mp3',\n                  'http://www.zhlongyin.com/UploadFiles/xrxz/2012/2/201202201555569985.mp3']\n        });\n        // setTimeout(function(){\n        //     _mp3._$refreshList({\n        //         list:[]\n        //     });\n        // }._$bind(this),5000);\n        // 2秒后开始播放\n        // setTimeout(function(){\n        //     _mp3._$play();\n        // }._$bind(this),2000);\n        // 5秒后切换歌曲列表\n        // setTimeout(function(){\n        //     _mp3._$refreshList({\n        //         list:['../../../qunit/res/海阔天空 - 豆瓣FM.mp3',\n        //               '../../../qunit/res/开始懂了 - 豆瓣FM.mp3']\n        //     });\n        // }._$bind(this),3000);\n        // setTimeout(function(){\n        //     _mp3._$play();\n        // },5000)\n        // setTimeout(function(){\n        //     _p._$$MP3Player._$recycle(_mp3);\n        // }._$bind(this),10000);\n\n        // setTimeout(function(){\n        //     var _mp3 = _p._$$MP3Player._$allocate({\n        //     parent:'box',\n        //     mode:0,\n        //     list:['../../../qunit/res/开始懂了 - 豆瓣FM.mp3']\n        // });\n        // }._$bind(this),15000);\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}mp3.test.js',['ui/audio/mp3'],f);\n});"
  },
  {
    "path": "src/ui/base.js",
    "content": "/*\n * ------------------------------------------\n * UI控件基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/base */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/util',\n    'util/event',\n    'util/template/tpl'\n],function(NEJ,_k,_e,_u,_t,_t0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * UI控件基类，框架及项目中所有涉及UI的控件均继承此类\n     *\n     * 脚本举例\n     * ```javascript\n     * // 分配控件实例\n     * NEJ.define([\n     *     'ui/base'\n     * ],function(_i,_p,_o,_f,_r){\n     *     var ctrl = _i._$allocate({\n     *         clazz:'xxx',\n     *         parent:document.body\n     *     });\n     *     ctrl._$appendTo(document.body);\n     *     // 如果在分配时传入了parent则这步可省略\n     *     ctrl._$appendTo(function(_body){\n     *         // 如果需要自定义body插入的位置可以输入函数，返回父容器节点\n     *         _parent.insertAdjacentElement('afterBegin',_body);\n     *         return _parent;\n     *     });\n     * });\n     * ```\n     *\n     * @class     module:ui/base._$$Abstract\n     * @extends   module:util/event._$$EventTarget\n     * @param     {Object}               arg0    - 可选配置参数\n     * @property  {String}               clazz   - 控件样式\n     * @property  {String|Node|Function} parent  - 控件所在容器节点或者追加控件节点执行函数\n     * @property  {Object}               dataset - 控件携带的数据集信息\n     */\n    _p._$$Abstract = _k._$klass();\n    _pro = _p._$$Abstract._$extend(_t._$$EventTarget);\n    /**\n     * 初始化\n     *\n     * @protected\n     * @method module:ui/base._$$Abstract#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__super();\n        _e._$dumpCSSText();\n        this.__initXGui();\n        this.__initNode();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/base._$$Abstract#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__doInitClass(_options.clazz);\n        this.__doInitDataset(_options.dataset);\n        this._$appendTo(_options.parent);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/base._$$Abstract#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        // clear parent\n        this.__doDelParentClass();\n        this.__doDelParentDataset();\n        delete this.__parent;\n        // clear body\n        _e._$removeByEC(this.__body);\n        _e._$delClassName(\n            this.__body,\n            this.__class\n        );\n        delete this.__class;\n    };\n    /**\n     * 初始化外观信息，子类实现具体逻辑\n     *\n     * @abstract\n     * @method module:ui/base._$$Abstract#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = _f;\n    /**\n     * 初始化节点，子类重写具体逻辑\n     *\n     * @protected\n     * @method module:ui/base._$$Abstract#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        if (!this.__seed_html){\n            this.__initNodeTemplate();\n        }\n        this.__body = _t0._$getNodeTemplate(this.__seed_html);\n        if (!this.__body){\n            this.__body = _e._$create('div',this.__seed_css);\n        }\n        _e._$addClassName(this.__body,this.__seed_css);\n    };\n    /**\n     * 动态构建控件节点模板，子类实现具体逻辑\n     *\n     * @abstract\n     * @method module:ui/base._$$Abstract#__initNodeTemplate\n     * @return {Void}\n     */\n    _pro.__initNodeTemplate = _f;\n    /**\n     * 添加节点样式\n     *\n     * @protected\n     * @method module:ui/base._$$Abstract#__doInitClass\n     * @param  {String} arg0 - 样式名称\n     * @return {Void}\n     */\n    _pro.__doInitClass = function(_clazz){\n        this.__class = _clazz||'';\n        _e._$addClassName(this.__body,this.__class);\n    };\n    /**\n     * 添加携带数据\n     *\n     * @protected\n     * @method module:ui/base._$$Abstract#__doInitDataset\n     * @param _dataset\n     * @private\n     */\n    _pro.__doInitDataset = function(_dataset){\n        this.__datamap = _u._$merge({},_dataset);\n        _e._$dataset(this.__body,this.__datamap);\n    };\n    /**\n     * 删除携带数据\n     *\n     * @protected\n     * @method module:ui/base._$$Abstract#__doDelParentDataset\n     * @private\n     */\n    _pro.__doDelParentDataset = function(){\n        _u._$forIn(\n            this.__datamap,function(v,k){\n                _e._$dataset(this.__body,k,'');\n            },this\n        );\n    };\n    /**\n     * 父节点增加辅助样式\n     *\n     * @protected\n     * @method module:ui/base._$$Abstract#__doAddParentClass\n     * @return {Void}\n     */\n    _pro.__doAddParentClass = function(){\n        if (!!this.__seed_css){\n            var _arr = this.__seed_css.split(/\\s+/);\n            _e._$addClassName(\n                this.__parent,\n                _arr.pop()+'-parent'\n            );\n        }\n    };\n    /**\n     * 父节点删除辅助样式\n     *\n     * @protected\n     * @method module:ui/base._$$Abstract#__doDelParentClass\n     * @return {Void}\n     */\n    _pro.__doDelParentClass = function(){\n        if (!!this.__seed_css){\n            var _arr = this.__seed_css.split(/\\s+/);\n            _e._$delClassName(\n                this.__parent,\n                _arr.pop()+'-parent'\n            );\n        }\n    };\n    /**\n     * 取当前控件节点\n     *\n     * 脚本举例\n     * ```javascript\n     * // _mask是一个继承了此基类的实例化对象\n     * // 获取当前控件的节点\n     *   _mask._$getBody();\n     * ```\n     *\n     * @method module:ui/base._$$Abstract#_$getBody\n     * @return {Node} 控件节点\n     */\n    _pro._$getBody = function(){\n        return this.__body;\n    };\n    /**\n     * 控件节点追加至容器\n     *\n     * 脚本举例\n     * ```javascript\n     * // _mask是一个继承了此基类的实例化对象\n     * _mask._$appendTo(document.body);\n     * // 还可以传方法\n     * _mask._$appendTo(function(_body){\n     *    // 根据情况插入节点\n     *    var _parent = document.body;\n     *    _parent.insertAdjacentElement('afterBegin',_body);\n     *    return _parent;\n     * });\n     * ```\n     *\n     * @method module:ui/base._$$Abstract#_$appendTo\n     * @param  {String|Node|Function} arg0 - 控件所在容器节点\n     * @return {Void}\n     */\n    _pro._$appendTo = function(_parent){\n        if (!this.__body) return;\n        this.__doDelParentClass();\n        if (_u._$isFunction(_parent)){\n            this.__parent = _parent(this.__body);\n        }else{\n            this.__parent = _e._$get(_parent);\n            if (!!this.__parent){\n                this.__parent.appendChild(this.__body);\n            }\n        }\n        this.__doAddParentClass();\n    };\n    /**\n     * 显示控件\n     *\n     * 脚本举例\n     * ```javascript\n     * // _mask是一个继承了此基类的实例化对象\n     * _mask._$show();\n     * ```\n     *\n     * @method module:ui/base._$$Abstract#_$show\n     * @return {Void}\n     */\n    _pro._$show = function(){\n        if (!this.__parent||!this.__body||\n             this.__body.parentNode==this.__parent){\n            return;\n        }\n        this.__parent.appendChild(this.__body);\n    };\n    /**\n     * 隐藏控件\n     *\n     * 脚本举例\n     * ```javascript\n     * // _mask是一个继承了此基类的实例化对象\n     * _mask._$hide();\n     * ```\n     *\n     * @method module:ui/base._$$Abstract#_$hide\n     * @return {Void}\n     */\n    _pro._$hide = function(){\n        _e._$removeByEC(this.__body);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/ui/carousel/carousel.js",
    "content": "﻿﻿/*\n * ------------------------------------------\n * 卡片播放器实现文件\n * @version  1.0\n * @author   huxueliang(huxueliang@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/carousel/carousel */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/platform',\n    'base/element',\n    'base/event',\n    'base/util',\n    'util/event',\n    'util/gesture/drag',\n    'util/timer/animation',\n    'ui/carousel/indicator'\n],function(NEJ,_k,_m,_e,_v,_u,_t,_t0,_t1,_i0,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 卡片播放器对象\n     *\n     * @class     module:ui/carousel/carousel._$$Carousel\n     * @extends   module:util/event._$$EventTarget\n     * @param     {Object}      config    - 可选配置参数\n     * @property  {String|Node} parent    - 卡片所在父容器节点\n     * @property  {Number}      mode      - 动画模式(1:3d;2:2d;3:left/top)\n     * @property  {Number}      current   - 当前选中项\n     * @property  {Number}      buffer    - 预加载卡片个数\n     * @property  {Boolean}     nofollow  - 无跟随\n     * @property  {Boolean}     nobounce  - 无弹性\n     * @property  {Object}      indicator - 指示器参数\n     */\n    /**\n     * 添加卡片\n     *\n     * @event  module:ui/carousel/carousel._$$Carousel#onaddcard\n     * @param  {Number} index - 卡片索引\n     *\n     */\n    /**\n     * 准备滚动到某张卡片\n     *\n     * @event  module:ui/carousel/carousel._$$Carousel#onbeforescroll\n     * @param  {Number}  index  -  卡片索引\n     * @param  {Boolean} islast - 是否最后一张\n     */\n    /**\n     * 滚动到某张卡片\n     *\n     * @event  module:ui/carousel/carousel._$$Carousel#onscroll\n     * @param  {Number}  index  -  卡片索引\n     * @param  {Boolean} islast - 是否最后一张\n     *\n     */\n    /**\n     * 回收卡片处理函数\n     *\n     * @event  module:ui/carousel/carousel._$$Carousel#onrecycle\n     * @param  {Number} index - 回收的卡片索引\n     * @param  {Object} node  - 卡片的容器节点\n     */\n    /**\n     * 弹性释放事件处理函数\n     *\n     * @event  module:ui/carousel/carousel._$$Carousel#onbouncerelease\n     * @param  {Event} arg0 - 事件对象\n     *\n     */\n    _p._$$Carousel = _k._$klass();\n    _pro = _p._$$Carousel._$extend(_t._$$EventTarget,!0);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__reset\n     * @param  {Object} arg0 - 重置属性\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__parent = _e._$get(_options.parent);\n        this.__mode = _options.mode||(_m._$SUPPORT.css3d?1:2);\n        this.__config = this.__getConfig();\n        this.__noBounce = !!_options.nobounce;\n        this.__noFollow = !!_options.nofollow;\n        this.__transitionProperty = this.__mode==3?(this.__config.v?'top':'left')\n                                                  :'-'+_m._$KERNEL.prefix.css+'-transform';\n        //init item config\n        this.__items={addList:[],delList:[],curList:[],aniList:[],\n                      buffer:this.__parent.children.length||parseInt(_options.buffer),\n                      curIndex:parseInt(_options.current)||0,strIndex:0};\n        if(this.__parent.children.length>0){\n            for(var i=0;i<this.__parent.children.length;i++){\n                this.__items.curList[i]=this.__parent.children[i];\n            }\n        }\n        //init events\n        this._$batEvent({\n                'onaddcard':_options.onaddcard,\n            'onbeforescroll':_options.onbeforescroll,\n                 'onscroll':_options.onscroll,\n                'onrecycle':_options.onrecycle||this.__onRecycleItem._$bind(this),\n          'onbouncerelease':_options.onbouncerelease\n        });\n        //init keyboard events\n        //init drag events\n        this.__doInitDomEvent([\n            [document,'keydown',this.__onKeyDown._$bind(this)],\n            [this.__parent,'touchmove',_v._$stopDefault],\n            [this.__parent,'dragbegin',this.__onDragStart._$bind(this)],\n            [this.__parent,'dragging',this.__onDrag._$bind(this)],\n            [this.__parent,'dragcomplete',this.__onDragEnd._$bind(this)],\n        ]);\n        //init indicator\n        if(_options.indicator){\n            this.__iopt = _options.indicator;\n            this.__iopt.onactive=this._$scrollTo._$bind(this);\n            this.__iopt.cindex=this.__items.curIndex;\n            if(this.__indicator){\n                this.__indicator=_i0._$$Indicator._$recycle(this.__indicator);\n            }\n            this.__indicator=_i0._$$Indicator._$allocate(this.__iopt);\n        }\n        this.__worh = _options[this.__config.l]||this.__parent[this.__config.o];\n        this.__scroll = 0;\n        //not webkitRequestAnimationFrame(multi-webview bug);\n        window.setTimeout(this._$scrollToCurrent._$bind(this,this.__items.curIndex),0);\n    };\n    /**\n     * 获得配置参数(子类实现)\n     *\n     * @abstract\n     * @method module:ui/carousel/carousel._$$Carousel#__getConfig\n     * @return {Object}    配置参数对象\n     */\n    _pro.__getConfig = f;\n    /**\n     * 检测键盘事件\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__onKeyDown\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onKeyDown = function(_event){\n        if(this.__transitionEnd)return;\n        if(_event.keyCode==37){//left\n            this._$scrollToPrev();\n        }else if(_event.keyCode==39){//right\n            this._$scrollToNext();\n        }\n    };\n    /**\n     * 获得当前卡片总长度\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__getLength\n     * @return {Number}\n     */\n    _pro.__getLength = function(){\n        return this.__items.curList.length\n    };\n    /**\n     * 判断当前图片是否最后一张\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__isLast\n     * @param  {Number} index - 当前图片索引\n     * @return {Boolean}\n     */\n    _pro.__isLast = function(_index){\n        return (_index||this.__items.curIndex)==this.__getLength()-1?!0:!1;\n    };\n    /**\n     * 判断是否滚动到下一张\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__isNext\n     * @param  {Number} arg0 - 滚动距离\n     * @return {Boolean}\n     */\n    _pro.__isNext = function(_movement){\n        return (_movement<0)&&Math.abs(_movement)>3;\n    }\n    /**\n     * 判断是否滚动到前一张\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__isPrev\n     * @param  {Number} arg0 - 滚动距离\n     * @return {Boolean}\n     */\n    _pro.__isPrev = function(_movement){\n        return (_movement>0)&&Math.abs(_movement)>3;\n    }\n    /**\n     * 拖动开始事件处理函数\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__onDragStart\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onDragStart = function(_event){\n        if(this.__isLock||(this.__transitionEnd&&this.__noFollow))return;\n        if((this.__transitionEnd)&&(!this.__noFollow))this.__doTransitionEnd();\n        //for ios default bounce bug (reflow)\n        if(!this.__config.v){\n            this.__horizontal = Math.abs(_event.detalX)>Math.abs(_event.detalY);\n        }else{\n            this.__horizontal = Math.abs(_event.detalY)>Math.abs(_event.detalX);\n        }\n        if(this.__horizontal)_v._$stop(_event);\n        this.__dragging = !0;\n    };\n    /**\n     * 拖动事件处理函数\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__onDrag\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onDrag = function(_event){\n        if(!this.__dragging||!this.__horizontal||\n            this.__isLock||(this.__transitionEnd&&this.__noFollow))return;\n        var _movement=this.__scroll=_event[this.__config.m];\n        if((_movement>0&&this.__items.curIndex==0)||(_movement<0&&this.__isLast())){\n            this.__scroll = !!this.__noBounce?0:_movement/2;\n        }\n        if(!this.__noFollow){\n            this.__updatePosition();\n        }else{\n            if(this.__isNext(_movement)){//may be next\n                this.__dragging = !1;\n                this._$scrollToNext();\n            }else if(this.__isPrev(_movement)){//prev\n                this.__dragging = !1;\n                this._$scrollToPrev();\n            }\n        }\n    };\n    /**\n     * 拖动结束事件处理函数\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__onDragEnd\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onDragEnd = function(_event){\n        _v._$stopClick(_event);\n        if(!this.__horizontal||this.__isLock||this.__noFollow)return;\n        var _movement= _event[this.__config.m],\n            _current = this.__items.curIndex,\n            _start=this.__items.strIndex,_event={};\n        if(this.__isNext(_movement)){//may be next\n            this._$scrollToNext();\n        }else if(this.__isPrev(_movement)){//may be prev\n            this._$scrollToPrev();\n        }else{\n            this.__addToAniList(_current);\n            this.__scrollTo(_current);\n        }\n    };\n    /**\n     * 弹性释放时\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__onBounceRelease\n     * @return {Void}\n     */\n    _pro.__onBounceRelease = function(){\n        if(this.__noFollow)return;\n        var _event={};\n        this._$dispatchEvent('onbouncerelease',_event);//scroll to first\n        this.__addToAniList(_items.curIndex);\n        this.__scrollTo(_items.curIndex,_event.offset);\n    }\n    /**\n     * 滚动事件\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__fireEvent\n     * @param  {Event}  arg0 - 事件对象\n     * @param  {Object} arg1 - 配置参数\n     * @return {Void}\n     */\n    _pro.__fireEvent = function(_event,_param){\n        var _items = this.__items;\n        _param = _param||o;\n        switch(_event){\n            case 'onbeforescroll':{\n                this._$dispatchEvent('onbeforescroll',{index:_items.curIndex\n                                                      ,nindex:_param.nindex\n                                                      ,direction:_param.direction\n                                                      ,isLast:this.__isLast(_items.curIndex)});\n                break;\n            }\n            case 'onscroll':{\n                this._$dispatchEvent('onscroll',{index:_items.curIndex\n                                                ,isLast:this.__isLast(_items.curIndex)});\n                break;\n            }\n        }\n    };\n    /**\n     * 待添加Item列表\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__addToAddList\n     * @param  {Number} arg0 - 项索引\n     * @return {Void}\n     */\n    _pro.__addToAddList = function(_index){\n        if(_index<0)return;\n        this.__items.addList.push(_index);\n    }\n    /**\n     * 待删除Item列表\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__addToDelList\n     * @param  {Number} arg0 - 项索引\n     * @return {Void}\n     */\n    _pro.__addToDelList = function(_index){\n        var _items = this.__items;\n        if(!!_items.curList[_index])\n            _items.delList.push(_index);\n    }\n    /**\n     * 动画播放列表\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__addToAniList\n     * @return {Void}\n     */\n    _pro.__addToAniList = function(){\n        var _items = this.__items;\n        for(var i=0;i<arguments.length;i++){\n            _items.aniList[+arguments[i]]=!0;\n        }\n    }\n    /**\n     * 滚动到指定卡片\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__scrollTo\n     * @param  {Number} arg0 - 卡片索引\n     * @param  {Number} arg1 - 偏移量\n     * @return {Void}\n     */\n    _pro.__scrollTo = function(_index,_offset){\n        this.__scroll = _offset||0;\n        this.__items.curIndex=_index;\n        this.__updatePosition();\n        if(!!this.__indicator)this.__indicator._$update(this.__items.curIndex);\n    };\n    /**\n     * 更新所有卡片的位置\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__updatePosition\n     * @return {Void}\n     */\n    _pro.__updatePosition = function(){\n        var _items = this.__items,\n            i=_items.curList.length-1;\n        if(_items.aniList.length>0){\n            this.__transitionEnd = !0;\n            _v._$addEvent(this.__parent,'transitionend',this.__onTransitionEnd._$bind(this));\n        }\n        while((!!_items.curList[i])&&(i>=0)){\n            if((i<=_items.curIndex+1)&&(i>=_items.curIndex-1)){\n                this.__setItemPosition(i);\n            }else{\n                this.__setItemPosition(i);\n            }\n            i--\n        }\n    };\n    /**\n     * 设置卡片的位置\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__setItemPosition\n     * @param  {Number} arg0 - 卡片索引\n     * @return {Void}\n     */\n    _pro.__setItemPosition = function(_index){\n        var _items=this.__items,\n            _item =_items.curList[_index],\n            _offset,\n            _transition;\n        _transition = this.__transitionProperty;\n        _transition+= _items.aniList[_index]?' 300ms linear':' 0ms linear';\n        _e._$setStyle(_item,'transition',_transition);\n        //caculate position\n        _offset = this.__getItemOffset(_index);\n        var _translate = this.__config.v?[0,_offset]:[_offset,0];\n        if(this.__mode==3){\n            if(this.__config.v){_item.style.top = _translate[1]+'px';\n            }else{_item.style.left = _translate[0]+'px';}\n        }else{\n            _e._$setStyle(_item,'transform','translate('+_translate[0]+'px,'+_translate[1]+'px)'\n                                             +((this.__mode==1)?' translateZ(0)':''));\n        }\n    };\n    /**\n     * 计算卡片偏移量\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__getItemOffset\n     * @param  {Number} arg0 - 项索引\n     * @return {Number} 偏移量\n     */\n    _pro.__getItemOffset = function(_index){\n        return this.__scroll+(-(this.__items.curIndex-_index)*this.__worh);\n    };\n    /**\n     * 添加卡片\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__addItem\n     * @param  {Number} arg0 - 开始索引\n     * @param  {Number} arg1 - 结束索引\n     * @return {Void}\n     */\n    _pro.__addItem = function(_start,_end){\n        if(_start<0)return;\n        var i,_current=this.__items.curIndex;\n        if(_current>_start&&_current<_end){\n            for(i=_current-1;i>=_start;i--)this._$dispatchEvent('onaddcard',i);\n            for(i=_current;i<=_end;i++)this._$dispatchEvent('onaddcard',i);\n        }else{\n            for(i=_start;i<=(_end||_start);i++)this._$dispatchEvent('onaddcard',i);\n        }\n    };\n    /**\n     * 滚动停止处理函数\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__onTransitionEnd\n     * @param  {Event} _event - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTransitionEnd = function(_event){\n        this.__doTransitionEnd();\n        this.__fireEvent('onscroll');\n    };\n    /**\n     * 动画结束处理函数\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__doTransitionEnd\n     * @return {Void}\n     */\n    _pro.__doTransitionEnd = function(){\n        var _that=this;\n        if(!_that.__transitionEnd)return;\n        _v._$clearEvent(_that.__parent,'transitionend');\n        _u._$forEach(_that.__items.addList,function(_item,_index,_list){\n            _that.__addItem(_item);\n        });\n        _u._$forEach(_that.__items.delList,function(_item,_index){\n            _that.__delItem(_item);\n        });\n        _that.__items.addList=[];\n        _that.__items.delList=[];\n        _that.__items.aniList=[];\n        _that.__scroll = 0;\n        _that.__transitionEnd = !1;\n    };\n    /**\n     * 控件销毁函数\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        if(this.__indicator)\n            this.__indicator=_i0._$$Indicator._$recycle(this.__indicator);\n        var i=this.__items.curList.length-1;\n        while(!!this.__items.curList[i]&&i>=0){\n            this.__delItem(i);\n            i--;\n        }\n        this._$clearEvent();\n        delete this.__parent;\n        delete this.__isLock;\n        delete this.__items;\n        delete this.__scroll;\n        delete this.__transitionEnd;\n        delete this.__transitionProperty;\n        this.__super();\n    };\n    /**\n     * 卡片回收\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__delItem\n     * @param  {Number} arg0 - 回收的卡片索引\n     * @return {Void}\n     */\n    _pro.__delItem = function(_index){\n        if(_index<0)return;\n        var _node = this.__items.curList[_index];\n        this.__parent.removeChild(_node);\n        if(_index == this.__items.curList.length-1){\n            this.__items.curList.pop();\n        }else{\n            delete this.__items.curList[_index];\n        }\n        this._$dispatchEvent('onrecycle',_index,_node);\n    };\n    /**\n     * 卡片回收默认处理\n     *\n     * @protected\n     * @method module:ui/carousel/carousel._$$Carousel#__onRecycleItem\n     * @param  {Number}       arg0 - 回收项的索引\n     * @param  {Node|String}  arg1 - 卡片的容器节点\n     * @return {Void}\n     */\n    _pro.__onRecycleItem = function(_index,_node){\n        _e._$remove(_node);\n    };\n    /**\n     * 锁住控件\n     * @method module:ui/carousel/carousel._$$Carousel#_$lock\n     * @param  {Boolean} arg0 - 是否加锁\n     * @return {Void}\n     */\n    _pro._$lock = function(_isLock){\n       this.__isLock = !!_isLock;\n    };\n    /**\n     * 刷新接口\n     * @method module:ui/carousel/carousel._$$Carousel#_$refresh\n     * @param    {Object} options - 刷新参数\n     * @property {Number} current - 当前页\n     * @return   {Void}\n     */\n    _pro._$refresh = function(_options){\n        _options = _options||{};\n        this.__worh = _options[this.__config.l]||this.__parent[this.__config.o];\n        //get item content again\n        this._$scrollToCurrent(_options.current||this.__items.curIndex);\n    };\n    /**\n     * 滚动到下一张\n     * @method module:ui/carousel/carousel._$$Carousel#_$scrollToNext\n     * @return {Void}\n     */\n    _pro._$scrollToNext = function(){\n        var _items = this.__items;\n        this.__fireEvent('onbeforescroll',{direction:'next',nindex:_items.curIndex+1});\n        //maybe asyn get data\n        for(var i=_items.curIndex+1;i<=_items.curIndex+_items.buffer+1;i++){\n            if(!_items.curList[i])this.__addToAddList(i);\n        }\n        if(this.__isLast()){//may be last\n            this.__onBounceRelease();\n        }else{\n            _items.curIndex +=1;\n            if(_items.curIndex>_items.buffer)_items.strIndex += 1;\n            this.__addToDelList(_items.curIndex-_items.buffer-1);\n            this.__addToAniList(_items.curIndex-1,_items.curIndex);\n            this.__scrollTo(_items.curIndex);\n        }\n    };\n    /**\n     * 滚动到上一张\n     * @method module:ui/carousel/carousel._$$Carousel#_$scrollToPrev\n     * @return {Void}\n     */\n    _pro._$scrollToPrev = function(){\n        var _items = this.__items;\n        this.__fireEvent('onbeforescroll',{direction:'prev',nindex:_items.curIndex-1});\n        if(this.__items.curIndex==0){\n            this.__onBounceRelease();\n        }else{\n            this.__addToAddList(_items.curIndex-_items.buffer-1);\n            this.__addToDelList(_items.curIndex+_items.buffer);\n            _items.curIndex -=1;\n            if(_items.curIndex>_items.buffer)_items.strIndex -= 1;\n            this.__addToAniList(_items.curIndex,_items.curIndex+1);\n            this.__scrollTo(this.__items.curIndex);\n        }\n    };\n    /**\n     * 滚到当前项\n     * @method module:ui/carousel/carousel._$$Carousel#_$scrollToCurrent\n     * @param  {Number} arg0 - 卡片索引\n     * @return {Void}\n     */\n    _pro._$scrollToCurrent = function(_index){\n        var _child = this.__parent.children,\n            _items = this.__items,\n            i=_items.curList.length-1,\n            _start=_items.strIndex=_index-_items.buffer>=0?_index-_items.buffer:0,\n            _end = _index+_items.buffer;\n        if((_child.length!=_items.buffer)||(_child.length==0)){\n            while((_items.curList[i])&&(i>=0)){\n                this.__delItem(this.__items.curList[i]);\n                i--\n            }\n            _items.curIndex=_index;\n            this.__addItem(_start,_end);\n        }\n        this.__scrollTo(_index);\n        this.__fireEvent('onbeforescroll',{nindex:_items.curIndex});\n        this.__fireEvent('onscroll');\n    };\n    /**\n     * 添加卡片到容器\n     * @method module:ui/carousel/carousel._$$Carousel#_$appendItem\n     * @param  {Object}      arg0 - 卡片索引\n     * @param  {Node|String} arg1 - 添加的卡片内容\n     * @return {Void}\n     */\n    _pro._$appendItem = function(_index,_node){\n        var _container = this.__parent,\n            _node = _u._$isString(_node)?_e._$html2node(_node):_node;\n        this.__items.curList[_index]=_node;\n        if(_index<this.__items.curIndex){\n            _container.insertAdjacentElement('afterBegin',_node);\n            this.__setItemPosition(_index);\n        }else{\n            _container.appendChild(_node);\n            this.__setItemPosition(_index);\n        }\n    };\n    /**\n     * 异步添加项到容器末尾\n     * @method module:ui/carousel/carousel._$$Carousel#_$appendMore\n     * @param  {String} arg0 - 添加的卡片内容\n     * @return {nej.ui._$$Carousel}\n     */\n    _pro._$appendMore = function(_html){\n        var _container = this.__parent,\n            _node = _e._$html2node(_html);\n        _container.appendChild(_node);\n        this.__items.curList[this.__items.curList.length]=_node;\n        this.__setItemPosition(this.__items.curList.length);\n    };\n    /**\n     * 返回当前卡片索引\n     * @method module:ui/carousel/carousel._$$Carousel#_$getCurrentIndex\n     * @return {Number}\n     */\n    _pro._$getCurrentIndex = function(){\n        return this.__items.curIndex;\n    }\n    /**\n     * 根据卡片索引获得卡片\n     * @method module:ui/carousel/carousel._$$Carousel#_$getItemByIndex\n     * @param  {Number} arg0 - 卡片索引\n     * @return {Node}\n     */\n    _pro._$getItemByIndex = function(_index){\n        return this.__items.curList[_index];\n    };\n    /**\n     * 滚动到指定项\n     * @method module:ui/carousel/carousel._$$Carousel#_$scrollTo\n     * @param  {Number} arg0 - 卡片索引\n     * @return {Void}\n     */\n    _pro._$scrollTo = function(_index){\n        if(_index<0)return;\n        if(_index==this.__items.curIndex-1){\n            this._$scrollToPrev();\n        }else if(_index==this.__items.curIndex+1){\n            this._$scrollToNext();\n        }else{this._$scrollToCurrent(_index);}\n    };\n\n    if (SMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/carousel/carousel.list.js",
    "content": "// link to ui/carousel/list for compatible\n// use ui/carousel/list for new project\nNEJ.define(['./list.js'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/carousel/carousel.x.js",
    "content": "// link to ui/carousel/x for compatible\n// use ui/carousel/x for new project\nNEJ.define(['./x.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/ui/carousel/carousel.y.js",
    "content": "// link to ui/carousel/y for compatible\n// use ui/carousel/y for new project\nNEJ.define(['./y.js'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/carousel/indicator.js",
    "content": "/*\n * ------------------------------------------\n * 指示器对象实现文件\n * @version  1.0\n * @author   huxueliang(huxueliang@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/carousel/indicator */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'util/event'\n],function(NEJ,_k,_e,_t,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 指示器对象\n     *\n     * @class     module:ui/carousel/indicator._$$Indicator\n     * @extends   module:util/event._$$EventTarget\n     * @param     {Object}       arg0   - 可选配置参数\n     * @property  {String|Node}  parent - 控件所在容器节点\n     * @property  {Number}       cindex - 当前指示项\n     * @property  {String}       cstyle - 当前指示项样式\n     */\n    /**\n     * 指定项触发事件\n     *\n     * @event  module:ui/carousel/indicator._$$Indicator#onactive\n     * @param  {Number} arg0 - 指定项在所有项目中的位置\n     *\n     */\n    _p._$$Indicator = _k._$klass();\n    _pro = _p._$$Indicator._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/carousel/indicator._$$Indicator#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__body = _e._$get(_options.parent);\n        this.__cstyle = _options.cstyle;\n        this.__doInitDomEvent([\n            [this.__body,'tap',this.__onActive._$bind(this)]\n        ]);\n        this._$setEvent('onactive',_options.onactive);\n        this._$update(_options.cindex);\n    };\n    /**\n     * 点击指示器事件\n     *\n     * @protected\n     * @method module:ui/carousel/indicator._$$Indicator#__onActive\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onActive = function(_event){\n        var _element = _event.target;\n            _child = this.__body.children;\n        for(var i=0;i<_child.length;i++){\n            if(_child[i]==_element){\n                this._$dispatchEvent('onactive',i);\n                break;\n            }\n        }\n    };\n    /**\n     * 更新指示器位置\n     *\n     * @method module:ui/carousel/indicator._$$Indicator#_$update\n     * @param  {Number} arg0 - 当前项索引\n     * @return {Void}\n     */\n    _pro._$update = function(_current){\n        var _child = this.__body.children,\n            _ntmp=_e._$getByClassName(this.__body,this.__cstyle);\n        if(!!_ntmp&&_ntmp.length>0){\n            for(var i=0;i<_ntmp.length;i++){\n                _e._$delClassName(_ntmp[i],this.__cstyle);\n            }\n        }\n        _e._$addClassName(_child[_current],this.__cstyle);\n        this.__current = _current;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/carousel/list.js",
    "content": "/*\n * ------------------------------------------\n * 卡片播放器列表实现文件\n * @version  1.0\n * @author   huxueliang(huxueliang@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/carousel/list */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'util/event',\n    'ui/loading/loading',\n    'ui/carousel/x'\n],function(NEJ,_k,_e,_t,_i0,_i1,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 卡片播放器对象\n     *\n     * @class    module:util/carousel/list._$$CarouselList 卡片播放器控件\n     * @extends  module:util/event._$$EventTarget\n     * @param    {Object} arg0 - 可选配置参数\n     * @property {String|Node} parent    - 卡片所在父容器节点\n     * @property {Number}      current   - 当前选中项\n     * @property {Number}      buffer    - 预加载卡片个数\n     * @property {Object}      indicator - 指示器参数\n     */\n    /**\n     * 滚动到某张卡片\n     *\n     * @event  module:ui/carousel/list._$$CarouselList#onscroll\n     * @param  {Number} index - 卡片索引\n     */\n    /**\n     * 追加卡片(异步)\n     *\n     * @event  module:ui/carousel/list._$$CarouselList#onaddmore\n     *\n     */\n    _p._$$CarouselList = _k._$klass();\n    _pro = _p._$$CarouselList._$extend(_t._$$EventTarget);\n    _pro.__init = function(_options){\n        this.__super();\n        this.__initLoading();\n    };\n    /**\n     * 初始化加载控件\n     *\n     * @protected\n     * @method module:util/carousel/list._$$CarouselList#__initLoading\n     * @return {Void}\n     */\n    _pro.__initLoading = function(){\n        this.__lnode = document.createElement('div');\n        this.__lnode.style.position = 'absolute';\n        this.__lnode.style.top = '50%';\n        this.__lnode.style.left = '100%';\n    };\n    /**\n     * 控件重置函数\n     *\n     * @protected\n     * @method module:util/carousel/list._$$CarouselList#__reset\n     * @param  {Object} arg0 - 重置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this._$setEvent('onscroll',_options.onscroll);\n        this._$setEvent('onaddmore',_options.onaddmore);\n        _options.onscroll = this.__onScroll._$bind(this);\n        _options.onbouncerelease = this.__onBounceRelease._$bind(this);\n        this.__buffer = _options.buffer||0;\n        if(!this.__carousel)this.__carousel = _i1._$$CarouselX._$allocate(_options);\n        if(!this.__loading)this.__loading = _i0._$$Loading._$allocate({parent:this.__lnode});\n    };\n    /**\n     * 滚动回调函数\n     *\n     * @protected\n     * @method module:util/carousel/list._$$CarouselList#__onScroll\n     * @param  {Number} arg0 - 卡片索引\n     * @param  {Object} arg1 - 是否最后一张卡片\n     * @return {Void}\n     */\n    _pro.__onScroll = function(_index,_isLast){\n        this._$dispatchEvent('onscroll',_index);\n        if(_isLast){\n            this.__carousel._$getCardByIndex(_index).appendChild(this.__lnode);\n        }\n    };\n    /**\n     * 弹性释放处理函数\n     *\n     * @protected\n     * @method module:util/carousel/list._$$CarouselList#__onBounceRelease\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onBounceRelease= function(_event){\n        _event.offset=-(1.5*this.__lnode.offsetWidth);\n        if(this.__load) return;\n        this.__load = !0;\n        this._$dispatchEvent('onaddmore');\n    };\n    /**\n     * 列表回收处理函数\n     *\n     * @protected\n     * @method module:util/carousel/list._$$CarouselList#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__carousel = _i1._$$CarouselX._$recycle(this.__carousel);\n        this.__loading = _i0._$$Loading._$recycle(this.__loading);\n        _e._$removeByEC(this.__lnode);\n        this._$clearEvent();\n        this.__super();\n    };\n    /**\n     * 添加卡片（同步）\n     * @method module:util/carousel/list._$$CarouselList#_$appendItem\n     * @param  {Number}      arg0 - 要添加的卡片索引\n     * @param  {String|Node} arg1 - 要添加的卡片内容或节点\n     * @return {Void}\n     */\n    _pro._$appendItem = function(_index,_node){\n        this.__carousel._$appendItem(_index,_node);\n    };\n    /**\n     * 滚动下一张卡片\n     * @method module:util/carousel/list._$$CarouselList#_$scrollToNext\n     * @param  {Number} arg0 - 卡片索引\n     * @return {Void}\n     */\n    _pro._$scrollToNext = function(_index){\n        this.__carousel._$scrollToNext(_index);\n    };\n    /**\n     * 滚动上一张卡片\n     * @method module:util/carousel/list._$$CarouselList#_$scrollToPrev\n     * @param  {Number} arg0 - 卡片索引\n     * @return {Void}\n     */\n    _pro._$scrollToPrev = function(_index){\n        this.__carousel._$scrollToPrev(_index);\n    };\n    /**\n     * 滚动到指定卡片\n     * @method module:util/carousel/list._$$CarouselList#_$scrollTo\n     * @param  {Object} arg0 - 卡片索引\n     * @return {Void}\n     */\n    _pro._$scrollTo = function(_index){\n        this.__carousel._$scrollTo(_index);\n    };\n    /**\n     * 滚动到指定卡片\n     * @method module:util/carousel/list._$$CarouselList#_$refresh\n     * @param  {Number} arg0 - 卡片索引\n     * @return {Void}\n     */\n    _pro._$refresh = function(_index){\n        this.__carousel._$refresh();\n    };\n    /**\n     * 往列表末尾追加卡片（异步）\n     * @method module:util/carousel/list._$$CarouselList#_$appendMore\n     * @param  {Array} arg0 - 要添加的卡片内容数组\n     * @return {Void}\n     */\n    _pro._$appendMore = function(_array){\n        this.__load = !1;\n        _e._$removeByEC(this.__lnode);\n        if(!_array||_array.length<=0)return;\n        for(var i=0;i<Math.min(_array.length,this.__buffer);i++){\n            this.__carousel._$appendMore(_array[i]);\n        }\n        window.setTimeout((function(){this.__carousel._$scrollToNext();})._$bind(this),0);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n})"
  },
  {
    "path": "src/ui/carousel/test/carousel.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<meta name=\"viewport\" content=\"width=device-width,user-scalable=no\">\n\t\t<title>carousel测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style type=\"text/css\">\n\t\t\timg{position:absolute;width:270px;}\n\t\t    #carousel-box{position:relative;width:270px;height:130px;overflow:hidden;}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit carousel test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n \t\t<h2>10秒后统计卡片播放结果</h2>\n\t\t<div id=\"carousel-box\"></div>\n\t\t<div style=\"height:1000px;width:1px\">&nbsp;</div>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./carousel.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/ui/carousel/test/carousel.test.js",
    "content": "var f = function(){\n\t//定义测试模块\n\tmodule(\"carousel\");\n\tvar _  = NEJ.P,\n        _v = _('nej.v'),\n\t\t_e = _('nej.e'),\n\t\t_p = _('nej.ui');\n\n\n\t//开始单元测试\n\ttest('carouselX',function(){\n\t\tstop();\n//\t\t_v._$addEvent('carousel-box','touchstart',_v._$stopDefault);\n//\t\t_v._$addEvent('carousel-box','touchmove',_v._$stopDefault);\n\t\tvar _cx = _p._$$CarouselX._$allocate({\n\t\t\tparent:_e._$get('carousel-box'),\n\t\t\tmode:1,\n\t\t\tbuffer:10,\n\t\t\tcurrent:2,\n\t\t\tonaddcard:function(_index){\n\t\t\t\tvar _img = _e._$create('img');\n\t\t\t\t_img.draggable = false;\n\t\t\t\t_img.src = 'http://www.baidu.com/img/baidu_sylogo1.gif';\n\t\t\t\t_cx._$appendItem(_index,_img);\n\t\t\t},\n\t\t\tonscrollstart:function(_index){\n\t\t\t\tok(true,'onscrollstart')\n\t\t\t},\n\t\t\tonscroll:function(_index){\n\t\t\t\tok(true,'onscroll')\n\t\t\t},\n\t\t\tonbouncerelease:function(_index){\n\t\t\t\tok(true,'onbouncerelease')\n\t\t\t}\n\t\t});\n\t\t\tsetTimeout(function(){\n\t\t\t\tstart();\n\t\t\t},10000);\n\n\t});\n\n\t//开始单元测试\n\ttest('carouselY',function(){\n\t\texpect(0);\n\t});\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n\tdefine('{pro}carousel.test.js',['ui/carousel/carousel.x','ui/carousel/carousel.y'],f);\n});"
  },
  {
    "path": "src/ui/carousel/x.js",
    "content": "/*\n * ------------------------------------------\n * 水平模块播放器实现文件\n * @version  1.0\n * @author   huxueliang(huxueliang@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/carousel/x */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'ui/carousel/carousel'\n],function(NEJ,_k,_i0,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 卡片水平播放器对象\n     *\n     * @class   module:ui/carousel/x._$$CarouselX\n     * @extends module:ui/carousel/carousel._$$Carousel\n     */\n    _p._$$CarouselX = _k._$klass();\n    _pro = _p._$$CarouselX._$extend(_i0._$$Carousel);\n    /**\n     * 获得配置参数\n     *\n     * @protected\n     * @method module:ui/carousel/x._$$CarouselX#__getConfig\n     * @return {Object}    配置参数对象\n     */\n    _pro.__getConfig = function(){\n        return {\n            m:'moveX',\n            p:'m41',\n            l:'width',\n            o:'offsetWidth',\n            v:!1\n        };\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});\n\n"
  },
  {
    "path": "src/ui/carousel/y.js",
    "content": "/*\n * ------------------------------------------\n * 卡片垂直播放器实现文件\n * @version  1.0\n * @author   huxueliang(huxueliang@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/carousel/y */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'ui/carousel/carousel'\n],function(NEJ,_k,_i0,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 卡片水平播放器对象\n     *\n     * @class   module:ui/carousel/y._$$CarouselY\n     * @extends module:ui/carousel/carousel._$$Carousel\n     */\n    _p._$$CarouselY = _k._$klass();\n    _pro = _p._$$CarouselY._$extend(_i0._$$Carousel);\n    /**\n     * 获得配置参数\n     *\n     * @protected\n     * @method module:ui/carousel/y._$$CarouselY#__getConfig\n     * @return {Object}    配置参数对象\n     */\n    _pro.__getConfig = function(){\n        return {\n            m:'moveY',\n            p:'m42',\n            l:'height',\n            o:'offsetHeight',\n            v:!0\n        };\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});\n\n"
  },
  {
    "path": "src/ui/carousel.list/carousel.list.js",
    "content": "﻿// link to ui/carousel/list for compatible\n// use ui/carousel/list for new project\nNEJ.define(['ui/carousel/list'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/colorpick/colorpanel.css",
    "content": ".#<uispace>{width:160px;margin:0 auto;overflow:hidden;$<user-select>:none;}\n.#<uispace> .zbg{background:url(#<root>nej_color_btn.png) no-repeat -50px -50px;}\n.#<uispace> .zwrp{position:relative;padding:3px;zoom:1;cursor:default;font-size:1px;}\n.#<uispace> .zwrp .zdot{position:absolute;top:0;left:0;height:8px;overflow:hidden;}\n.#<uispace> .zwrp .zshw{height:104px;border:1px solid #bdbabd;}\n.#<uispace> .zpnl{float:left;}\n.#<uispace> .zpnl .zdot{width:8px;background-position:0 0;}\n.#<uispace> .zpnl .zshw{width:104px;background:url(#<root>nej_color.png) no-repeat;}\n.#<uispace> .zhlt{float:right;padding:3px 7px;}\n.#<uispace> .zhlt .zdot{width:44px;height:9px;background-position:0 -30px;}\n.#<uispace> .zhlt .zshw{width:26px;background:url(#<root>nej_color_mask.png) repeat-x;}"
  },
  {
    "path": "src/ui/colorpick/colorpanel.html",
    "content": "<div>\n  <div class=\"zwrp zpnl js-ztag\">\n    <span class=\"zdot zbg js-ztag\">&nbsp;</span>\n    <div class=\"zshw\">&nbsp;</div>\n  </div>\n  <div class=\"zwrp zhlt js-ztag\">\n    <span class=\"zdot zbg js-ztag\">&nbsp;</span>\n    <div class=\"zshw js-ztag\">&nbsp;</div>\n  </div>\n</div>"
  },
  {
    "path": "src/ui/colorpick/colorpanel.js",
    "content": "/*\n * ------------------------------------------\n * 颜色面板控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/colorpick/colorpanel */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/config',\n    'base/element',\n    'base/event',\n    'util/template/tpl',\n    'util/slider/y',\n    'util/slider/xy',\n    'util/color/color',\n    'ui/base',\n    'text!./colorpanel.css',\n    'text!./colorpanel.html'\n],function(NEJ,_k,_c,_e,_v,_t0,_t1,_t2,_i0,_i,_css,_html,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 颜色选择面板控件\n     *\n     * 结构举例\n     * ```html\n     * <div id='colorpanel-box'></div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'ui/colorpick/colorpanel'\n     * ],function(_i0,_p,_o,_f,_r){\n     *     var _cp = _i0._$$ColorPanel._$allocate({\n     *         parent:'colorpanel-box',\n     *         onchange:function(_color){\n     *             // 选择颜色或者亮度的时候触发\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @class    module:ui/colorpick/colorpanel._$$ColorPanel\n     * @uses     module:util/slider/xy._$$SliderXY\n     * @uses     module:util/slider/y._$$SliderY\n     * @extends  module:ui/event._$$Abstract\n     * \n     * @param    {Object} arg0         - 可选配置参数\n     * @property {String} color        - RGB颜色值\n     * @property {String} defaultColor - 默认颜色，默认为#fff\n     */\n    /**\n     * 颜色变化触发事件\n     *\n     * @event  module:ui/colorpick/colorpanel._$$ColorPanel#onchange\n     * @param  {String} arg0 - RGB颜色串\n     */\n    _p._$$ColorPanel = _k._$klass();\n    _pro = _p._$$ColorPanel._$extend(_i._$$Abstract);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:ui/colorpick/colorpanel._$$ColorPanel#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__hsl  = {};\n        this.__sopt = {\n            onchange:this.__onLightChange._$bind(this)\n        };\n        this.__dopt = {\n            onchange:this.__onHueSatChange._$bind(this)\n        };\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/colorpick/colorpanel._$$ColorPanel#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__default = _options.defaultColor||'#fff';\n        this.__lslide = _t2._$$SliderXY._$allocate(this.__dopt);\n        this.__rslide = _t1._$$SliderY._$allocate(this.__sopt);\n        this._$setColor(_options.color);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/colorpick/colorpanel._$$ColorPanel#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__hsl = {};\n        this.__lslide._$recycle();\n        delete this.__lslide;\n        this.__rslide._$recycle();\n        delete this.__rslide;\n        this.__super();\n    };\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/colorpick/colorpanel._$$ColorPanel#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = (function(){\n        var _seed_css = _e._$pushCSSText(_css,{\n                root:_c._$get('root')\n            }),\n            _seed_html= _t0._$addNodeTemplate(_html);\n        return function(){\n            this.__seed_css  = _seed_css;\n            this.__seed_html = _seed_html;\n        };\n    })();\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method module:ui/colorpick/colorpanel._$$ColorPanel#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        var _list = _e._$getByClassName(\n            this.__body,'js-ztag'\n        );\n        this.__dopt.track = _list[0];\n        this.__dopt.thumb = _list[1];\n        this.__sopt.track = _list[2];\n        this.__sopt.thumb = _list[3];\n        this.__nlprv = _list[4];\n    };\n    /**\n     * 亮度变化触发事件\n     *\n     * @protected\n     * @method module:ui/colorpick/colorpanel._$$ColorPanel#__onLightChange\n     * @param  {Object} arg0 - 位置信息\n     * @return {Void}\n     */\n    _pro.__onLightChange = function(_event){\n        var _light = 1-_event.y.rate;\n        if (_light==this.__hsl.l){\n            return;\n        }\n        this.__hsl.l = _light;\n        this._$dispatchEvent(\n            'onchange',\n            _i0._$hsl2color(this.__hsl)\n        );\n    };\n    /**\n     * 色度饱和度变化触发事件\n     *\n     * @protected\n     * @method module:ui/colorpick/colorpanel._$$ColorPanel#__onHueSatChange\n     * @param  {Object} arg0 - 位置信息\n     * @return {Void}\n     */\n    _pro.__onHueSatChange = function(_event){\n        var _hue = _event.x.rate,\n            _sat = 1-_event.y.rate;\n        if (_hue==this.__hsl.h&&\n            _sat==this.__hsl.s){\n            return;\n        }\n        this.__hsl.h = _hue;\n        this.__hsl.s = _sat;\n        _e._$setStyle(\n            this.__nlprv,'backgroundColor',\n            _i0._$hsl2color({\n                h:this.__hsl.h,\n                s:this.__hsl.s,\n                l:0.5\n            })\n        );\n        this._$dispatchEvent(\n            'onchange',\n            _i0._$hsl2color(this.__hsl)\n        );\n    };\n    /**\n     * 设置颜色\n     *\n     * 脚本举例\n     * ```javascript\n     * // 先把颜色转成rgb，然后转成hsl,在一个面板设置sh，在另外一个面板设置l\n     * _cp._$setColor('#000');\n     * ```\n     *\n     * @method module:ui/colorpick/colorpanel._$$ColorPanel#_$setColor\n     * @param  {String} arg0 - 颜色值\n     * @return {Void}\n     */\n    _pro._$setColor = function(_color){\n        if (!_i0._$isColor(_color)){\n            _color = this.__default;\n        }\n        this.__hsl = _i0._$color2hsl(_color);\n        this.__lslide._$setPosition({\n            x:this.__hsl.h,\n            y:1-this.__hsl.s\n        });\n        this.__rslide._$setPosition({\n            y:1-this.__hsl.l\n        });\n        this._$dispatchEvent(\n            'onchange',_color\n        );\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/colorpick/colorpick.complex.js",
    "content": "// link to ui/colorpick/complex for compatible\n// use ui/colorpick/complex for new project\nNEJ.define(['./complex.js'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/colorpick/colorpick.css",
    "content": ".#<uispace> .zbx{background:url(<#root>nej_color_btn.png) no-repeat -50px -50px;}\n.#<uispace> .zinf{width:160px;margin:0 auto;padding-bottom:2px;overflow:hidden;font-size:12px;}\n.#<uispace> .zinf .zfl{float:left;}\n.#<uispace> .zinf .zes{width:19px;height:19px;margin:0 2px 0 3px;background-position:-22px 0;cursor:pointer;}\n.#<uispace> .zinf .zpv{width:17px;height:17px;border:1px solid #bdbabd;}\n.#<uispace> .zinf .ztxt{width:56px;height:13px;line-height:13px;}\n.#<uispace> .zinf .zbtn{width:49px;height:20px;line-height:20px;padding:0;cursor:pointer;}"
  },
  {
    "path": "src/ui/colorpick/colorpick.html",
    "content": "<div>\n  <div class=\"zinf\">\n    <span class=\"zfl zes zbx js-ztag\" title=\"清除颜色\">&nbsp;</span>\n    <span class=\"zfl zpv js-ztag\">&nbsp;</span>\n    <label class=\"zfl\">#<input class=\"ztxt js-ztag\" type=\"text\" maxlength=\"6\"/></label>\n    <input class=\"zfl zbtn js-ztag\" type=\"button\" value=\"确定\"/>\n  </div>\n</div>"
  },
  {
    "path": "src/ui/colorpick/colorpick.js",
    "content": "/*\n * ------------------------------------------\n * 颜色选择控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/colorpick/colorpick */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/config',\n    'base/element',\n    'base/event',\n    'util/template/tpl',\n    'util/color/color',\n    'ui/base',\n    'ui/colorpick/colorpanel',\n    'text!./colorpick.css',\n    'text!./colorpick.html'\n],function(NEJ,_k,_c,_e,_v,_t0,_t1,_i,_i0,_css,_html,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 颜色选择控件\n     *\n     * 页面结构举例\n     * ```html\n     * <div id='colorpanel-box'></div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'ui/colorpick/colorpick'\n     * ],function(_i0,_p,_o,_f,_r){\n     *     var _cp = _i0._$$ColorPick._$allocate({\n     *         parent:'colorpanel-box',\n     *         color:'默认rgb颜色',\n     *         defaultColor:'默认rgb颜色',\n     *         onchange:function(_event){\n     *             // 选择颜色或者亮度的时候触发\n     *             console.log(_event.color)\n     *         },\n     *         onselect:function(_color){\n     *             // 最后保存颜色的时候触发\n     *             console.log(_event.color)\n     *         }\n     *       });\n     * });\n     * ```\n     *\n     * @class    module:ui/colorpick/colorpick._$$ColorPick\n     * @uses     module:ui/colorpick/colorpanel._$$ColorPanel\n     * @extends  module:ui/base._$$Abstract\n     * @param    {Object} arg0         - 可选配置参数\n     * @property {String} color        - 颜色值\n     * @property {String} defaultColor - 默认颜色值\n     */\n    /**\n     * 颜色变化触发事件\n     *\n     * @event    module:ui/colorpick/colorpick._$$ColorPick#onchange\n     * @param    {Object} arg0  - 颜色信息\n     * @property {String} color - 颜色值\n     */\n    /**\n     * 确定选择颜色触发事件\n     *\n     * @event    module:ui/colorpick/colorpick._$$ColorPick#onselect\n     * @param    {Object} arg0  - 颜色信息\n     * @property {String} color - 颜色值\n     *\n     */\n    _p._$$ColorPick = _k._$klass();\n    _pro = _p._$$ColorPick._$extend(_i._$$Abstract);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:ui/colorpick/colorpick._$$ColorPick#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__popt = {\n            onchange:this.__onColorChange._$bind(this)\n        };\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/colorpick/colorpick._$$ColorPick#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__default = _options.defaultColor||'#fff';\n        this.__popt.color = _options.color;\n        this.__popt.defaultColor = this.__default;\n        this.__panel = _i0._$$ColorPanel._$allocate(this.__popt);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/colorpick/colorpick._$$ColorPick#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__panel._$recycle();\n        delete this.__panel;\n        this.__super();\n    };\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/colorpick/colorpick._$$ColorPick#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = (function(){\n        var _seed_css = _e._$pushCSSText(_css,{\n                root:_c._$get('root')\n            }),\n            _seed_html= _t0._$addNodeTemplate(_html);\n        return function(){\n            this.__seed_css  = _seed_css;\n            this.__seed_html = _seed_html;\n        };\n    })();\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method module:ui/colorpick/colorpick._$$ColorPick#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        var _list = _e._$getByClassName(this.__body,'js-ztag');\n        this.__ninput = _list[2];\n        this.__npreview = _list[1];\n        this.__popt.parent = this.__body;\n        _v._$addEvent(\n            _list[0],'click',\n            this.__onColorClear._$bind(this)\n        );\n        _v._$addEvent(\n            _list[2],'enter',\n            this.__onColorSelect._$bind(this)\n        );\n        _v._$addEvent(\n            _list[3],'click',\n            this.__onColorSelect._$bind(this)\n        );\n    };\n    /**\n     * 清除颜色\n     *\n     * @protected\n     * @method module:ui/colorpick/colorpick._$$ColorPick#__onColorClear\n     * @return {Void}\n     */\n    _pro.__onColorClear = function(){\n        this.__panel._$setColor(this.__default);\n    };\n    /**\n     * 颜色变化触发事件\n     *\n     * @protected\n     * @method module:ui/colorpick/colorpick._$$ColorPick#__onColorChange\n     * @param  {String} arg0 - 颜色值\n     * @return {Void}\n     */\n    _pro.__onColorChange = function(_color){\n        this.__ninput.value = _color.substr(1);\n        _e._$setStyle(this.__npreview,'backgroundColor',_color);\n        this._$dispatchEvent('onchange',{color:_color});\n    };\n    /**\n     * 确定选择颜色\n     *\n     * @protected\n     * @method module:ui/colorpick/colorpick._$$ColorPick#__onColorSelect\n     * @return {Void}\n     */\n    _pro.__onColorSelect = function(){\n        var _color = '#'+this.__ninput.value.trim();\n        if (!_t1._$isColor(_color)){\n            return;\n        }\n        this.__panel._$setColor(_color);\n        _color = '#'+this.__ninput.value.trim();\n        this._$dispatchEvent('onselect',{color:_color});\n    };\n    /**\n     * 设置颜色\n     *\n     * 脚本举例\n     * ```javascript\n     * // 先把颜色转成rgb，然后转成hsl,在一个面板设置sh，在另外一个面板设置l\n     * _cp._$setColor('#ccc');\n     * ```\n     *\n     * @method module:ui/colorpick/colorpick._$$ColorPick#_$setColor\n     * @param  {String} arg0 - 颜色值\n     * @return {Void}\n     */\n    _pro._$setColor = function(_color){\n        this.__panel._$setColor(_color);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/colorpick/colorpick.simple.js",
    "content": "// link to ui/colorpick/simple for compatible\n// use ui/colorpick/simple for new project\nNEJ.define(['./simple.js'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/colorpick/complex.html",
    "content": "{list xlist as x}\n<a class=\"zitm zitm2\" style=\"background-color:#${x}\" data-value=\"#${x}\" href=\"#\">&nbsp;</a>\n{/list}"
  },
  {
    "path": "src/ui/colorpick/complex.js",
    "content": "/*\n * ------------------------------------------\n * 颜色选择控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/colorpick/complex */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    'base/element',\n    'ui/colorpick/simple',\n    'util/template/jst',\n    'text!./complex.html'\n],function(NEJ,_k,_u,_e,_i0,_t0,_html,_p,_o,_f,_r){\n    var _pro,\n        _seed_color = _t0._$add(_html);\n    /**\n     * 颜色选择控件\n     *\n     * 页面结构举例\n     * ```html\n     * <div id='colorpanel-box'></div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'ui/colorpick/complex'\n     * ],function(_i0,_p,_o,_f,r){\n     *     var _cp = _i0._$$ComplexColorPick._$allocate({\n     *         parent:'colorpanel-box',\n     *         defaultColor:'默认rgb颜色',\n     *         onselect:function(_event){\n     *             console.log(_event.color)\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @class    module:ui/colorpick/complex._$$ComplexColorPick\n     * @extends  module:ui/colorpick/simple._$$SimpleColorPick\n     * @param    {Object} arg0 - 可选配置参数\n     * @property {String} defaultColor - 默认颜色值\n     */\n    /**\n     * 确定选择颜色触发事件\n     *\n     * @event    module:ui/colorpick/complex._$$ComplexColorPick#onselect\n     * @param    {Object} arg0  - 颜色信息\n     * @property {String} color - 颜色值\n     *\n     */\n    _p._$$ComplexColorPick = _k._$klass();\n    _pro = _p._$$ComplexColorPick._$extend(_i0._$$SimpleColorPick);\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method module:ui/carousel/complex._$$ComplexColorPick#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        _e._$addClassName(this.__nbox,'zbox2');\n    };\n    /**\n     * 绘制可选颜色列表\n     *\n     * @protected\n     * @method module:ui/carousel/complex._$$ComplexColorPick#__doRenderColorList\n     * @return {Void}\n     */\n    _pro.__doRenderColorList = (function(){\n        var _xlist = ['00','33','66','99','cc','ff'],\n            _ylist = ['ff0000','00ff00','0000ff','ffff00','00ffff','ff00ff'];\n        return function(){\n            var _arr = [],\n                _test = ['','','',''];\n            // top panel\n            _u._$forEach(\n                _xlist,function(_value,_index){\n                    _arr.push(_test.join(_value));\n                    _arr.push('000000');\n                    for(var i=0;i<3;i++){\n                        for(var j=0;j<6;j++){\n                            _arr.push(_xlist[i]+_xlist[j]+_xlist[_index]);\n                        }\n                    }\n                }\n            );\n            // bottom panel\n            _u._$forEach(\n                _xlist,function(_value,_index){\n                    _arr.push(_ylist[_index]);\n                    _arr.push('000000');\n                    for(var i=3;i<6;i++){\n                        for(var j=0;j<6;j++){\n                            _arr.push(_xlist[i]+_xlist[j]+_xlist[_index]);\n                        }\n                    }\n                }\n            );\n            _t0._$render(\n                this.__nbox,_seed_color,{\n                    xlist:_arr\n                }\n            );\n        };\n    })();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/colorpick/demo/colorpanel.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>demo for colorpick</title>\n    <meta charset=\"utf-8\" />\n    <style>\n        body{padding-top:10px;}\n    </style>\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.getElementById('lbox')\n                  .insertAdjacentElement('afterBegin',p);\n      }\n    </script>\n  </head>\n  <body>\n    <div id=\"cbox\"></div>\n    <div id=\"lbox\"></div>\n\n    <script>\n      window.NEJ_CONF = {\n          root:'../../../../res/'\n      };\n    </script>\n    <script src=\"../../../define.js\"></script>\n    <script>\n      NEJ.define([\n          '../colorpanel.js',\n          'util/color/color'\n      ],function(_i,x){\n          var _colorpick = _i._$$ColorPanel._$allocate({\n              parent:'cbox',\n              defaultColor:'#ffddcc',\n              onchange:function(_color){\n                  log('change color -> '+_color);\n                  log('color to rgb -> '+ JSON.stringify(x._$color2rgb(_color)));\n              }\n          });\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/ui/colorpick/demo/colorpick.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>demo for colorpick</title>\n    <meta charset=\"utf-8\" />\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n  </head>\n  <body>\n    <script>\n      window.NEJ_CONF = {\n          root:'../../../../res/'\n      };\n    </script>\n    <script src=\"../../../define.js\"></script>\n    <script>\n      NEJ.define([\n          '../colorpick.js'\n      ],function(_i){\n          var _colorpick = _i._$$ColorPick._$allocate({\n              parent:document.body,\n              color:'#f00',\n              defaultColor:'#fdc',\n              onchange:function(_event){\n                  log('change color -> '+_event.color);\n              },\n              onselect:function(_event){\n                  log('select color -> '+_event.color);\n              }\n          });\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/ui/colorpick/demo/complex.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <title>demo for colorpick</title>\n    <meta charset=\"utf-8\" />\n    <script>\n        function log(m){\n            var p = document.createElement('p');\n            p.innerHTML = m;\n            document.body.appendChild(p);\n        }\n    </script>\n</head>\n<body>\n<script>\n    window.NEJ_CONF = {\n        root:'../../../../res/'\n    };\n</script>\n<script src=\"../../../define.js\"></script>\n<script>\n    NEJ.define([\n        '../complex.js'\n    ],function(_i){\n        var _colorpick = _i._$$ComplexColorPick._$allocate({\n            parent:document.body,\n            color:'#f00',\n            defaultColor:'#fdc',\n            onchange:function(_event){\n                log('change color -> '+_event.color);\n            },\n            onselect:function(_event){\n                log('select color -> '+_event.color);\n            }\n        });\n    });\n</script>\n</body>\n</html>"
  },
  {
    "path": "src/ui/colorpick/demo/simple.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <title>demo for colorpick</title>\n    <meta charset=\"utf-8\" />\n    <script>\n        function log(m){\n            var p = document.createElement('p');\n            p.innerHTML = m;\n            document.body.appendChild(p);\n        }\n    </script>\n</head>\n<body>\n<script>\n    window.NEJ_CONF = {\n        root:'../../../../res/'\n    };\n</script>\n<script src=\"../../../define.js\"></script>\n<script>\n    NEJ.define([\n        '../simple.js'\n    ],function(_i){\n        var _colorpick = _i._$$SimpleColorPick._$allocate({\n            parent:document.body,\n            color:'#f00',\n            defaultColor:'#fdc',\n            onchange:function(_event){\n                log('change color -> '+_event.color);\n            },\n            onselect:function(_event){\n                log('select color -> '+_event.color);\n            }\n        });\n    });\n</script>\n</body>\n</html>"
  },
  {
    "path": "src/ui/colorpick/simple.css",
    "content": ".#<uispace>{text-align:left;}\n.#<uispace> .zdft{display:block;padding:3px 1px 3px 5px;margin:3px;cursor:pointer;}\n.#<uispace> .zdft:hover{padding:2px 0 2px 4px;background:#ffeec2;border:1px solid #000080;text-decoration:none;}\n.#<uispace> .zprv{display:block;width:28px;height:11px;overflow:hidden;border:1px solid #aca899;}\n.#<uispace> .zbox{width:152px;margin:0 5px;overflow:hidden;}\n.#<uispace> .zbox .zitm{display:block;float:left;width:11px;height:11px;overflow:hidden;margin:3px;border:1px solid #aca899;cursor:pointer;}\n.#<uispace> .zbox2{width:220px;margin-left:9px;border-width:1px 0 0 1px;border-color:#000;border-style:solid;}\n.#<uispace> .zbox2 .zitm2{width:10px;height:10px;margin:-1px 0 0 -1px;border-color:#000;}"
  },
  {
    "path": "src/ui/colorpick/simple.html",
    "content": "<textarea name='ntp' id='#<seedHtml>'>\n  <div class=\"'+_seed_css+'\">\n    <a class=\"zdft\" title=\"去除颜色\" href=\"#\">\n      <span class=\"zprv j-flag\">&nbsp;</span>\n    </a>\n    <div class=\"zbox j-flag\"></div>\n  </div>\n</textarea>\n\n<textarea name='jst' id='#<seedColor>'>\n  {list xlist as x}\n  <a class=\"zitm\" title=\"${x.t}\" style=\"background-color:${x.v}\" data-value=\"${x.v}\" href=\"#\">&nbsp;</a>\n  {/list}\n</textarea>"
  },
  {
    "path": "src/ui/colorpick/simple.js",
    "content": "/*\n * ------------------------------------------\n * 颜色选择控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/colorpick/simple */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/config',\n    'base/element',\n    'base/event',\n    'ui/base',\n    'util/template/tpl',\n    'util/template/jst',\n    'text!./simple.css',\n    'text!./simple.html'\n],function(NEJ,_k,_c,_e,_v,_i,_t0,_t1,_css,_html,_p,_o,_f,_r){\n    var _pro,\n        _seed_css = _e._$pushCSSText(_css,{root:_c._$get('root')}),\n        _seed_ui  = _t0._$parseUITemplate(_html),\n        _seed_html  = _seed_ui['seedHtml'],\n        _seed_color = _seed_ui['seedColor'];\n    /**\n     * 颜色选择控件\n     *\n     * 页面结构举例\n     * ```html\n     * <div id='colorpanel-box'></div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'ui/colorpick/simple'\n     * ],function(_i0,_p,_o,_f,_r){\n     *     var _cp = _i0._$$SimpleColorPick._$allocate({\n     *         parent:'colorpanel-box',\n     *         defaultColor:'默认rgb颜色',\n     *         onselect:function(_color){\n     *             // 最后保存颜色的时候触发\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @class     module:ui/colorpick/simple._$$SimpleColorPick\n     * @extends   module:ui/base._$$Abstract\n     * @param     {Object} arg0 - 可选配置参数\n     * @property  {String} arg0 - defaultColor 默认颜色值\n     */\n    /**\n     * 确定选择颜色触发事件\n     *\n     * @event    module:ui/colorpick/simple._$$SimpleColorPick#onselect\n     * @param    {Object} arg0  - 颜色信息\n     * @property {String} color - 颜色值\n     *\n     */\n    _p._$$SimpleColorPick = _k._$klass();\n    _pro = _p._$$SimpleColorPick._$extend(_i._$$Abstract);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/colorpick/simple._$$SimpleColorPick#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__default = _options.defaultColor||'#ffffff';\n        this.__doInitDomEvent([[\n            this.__nprv.parentNode,'click',\n            this.__onClearColor._$bind(this)\n        ],[\n            this.__nbox,'click',\n            this.__onSelectColor._$bind(this)\n        ],[\n            this.__nbox,'mouseover',\n            this.__onPreviewColor._$bind(this)\n        ]]);\n        this.__doPreviewColor(this.__default);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/colorpick/simple._$$SimpleColorPick#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__default;\n    };\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/colorpick/simple._$$SimpleColorPick#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css  = _seed_css;\n        this.__seed_html = _seed_html;\n    };\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method module:ui/colorpick/simple._$$SimpleColorPick#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        // 0 - color preview\n        // 1 - color list box\n        var _list = _e._$getByClassName(this.__body,'j-flag');\n        this.__nprv = _list[0];\n        this.__nbox = _list[1];\n        this.__doRenderColorList();\n    };\n    /**\n     * 绘制可选颜色列表\n     *\n     * @protected\n     * @method module:ui/colorpick/simple._$$SimpleColorPick#__doRenderColorList\n     * @return {Void}\n     */\n    _pro.__doRenderColorList = (function(){\n        var _xlist = [\n            {t:'黑色',v:'#000000'},{t:'褐色',v:'#993300'},{t:'橄榄色',v:'#333300'},{t:'深绿',v:'#003300'},{t:'深青',v:'#003366'},{t:'深蓝',v:'#000080'},{t:'靛蓝',v:'#333399'},{t:'灰色-80%',v:'#333333'},\n            {t:'深红',v:'#800000'},{t:'橙色',v:'#ff6600'},{t:'深黄',v:'#808000'},{t:'绿色',v:'#008000'},{t:'青色',v:'#008080'},{t:'蓝色',v:'#0000ff'},{t:'蓝-灰',v:'#666699'},{t:'灰色-50%',v:'#808080'},\n            {t:'红色',v:'#ff0000'},{t:'浅橙色',v:'#ff9900'},{t:'酸橙色',v:'#99cc00'},{t:'海绿',v:'#339966'},{t:'水绿色',v:'#33cccc'},{t:'浅蓝',v:'#3366ff'},{t:'紫罗兰',v:'#800080'},{t:'灰色-40%',v:'#999999'},\n            {t:'粉红',v:'#ff00ff'},{t:'金色',v:'#ffcc00'},{t:'黄色',v:'#ffff00'},{t:'鲜绿',v:'#00ff00'},{t:'青绿',v:'#00ffff'},{t:'天蓝',v:'#00ccff'},{t:'梅红',v:'#993366'},{t:'灰色-25%',v:'#c0c0c0'},\n            {t:'玫瑰红',v:'#ff99cc'},{t:'茶色',v:'#ffcc99'},{t:'浅黄',v:'#ffff99'},{t:'浅绿',v:'#ccffcc'},{t:'浅青绿',v:'#ccffff'},{t:'淡蓝',v:'#99ccff'},{t:'淡紫',v:'#cc99ff'},{t:'白色',v:'#ffffff'}\n        ];\n        return function(){\n            _t1._$render(\n                this.__nbox,_seed_color,{\n                    xlist:_xlist\n                }\n            );\n        };\n    })();\n    /**\n     * 清除颜色\n     *\n     * @protected\n     * @method module:ui/colorpick/simple._$$SimpleColorPick#__onClearColor\n     * @param  {Event} arg0 - 事件信息\n     * @return {Void}\n     */\n    _pro.__onClearColor = function(_event){\n        _v._$stop(_event);\n        this.__doChangeColor(this.__default);\n    };\n    /**\n     * 颜色选择事件\n     *\n     * @protected\n     * @method module:ui/colorpick/simple._$$SimpleColorPick#__onSelectColor\n     * @param  {Event} arg0 - 事件信息\n     * @return {Void}\n     */\n    _pro.__onSelectColor = function(_event){\n        var _element = _v._$getElement(_event,'d:value');\n        if (!_element) return;\n        _v._$stop(_event);\n        this.__doChangeColor(\n            _e._$dataset(_element,'value')\n        );\n    };\n    /**\n     * 预览颜色\n     *\n     * @protected\n     * @method module:ui/colorpick/simple._$$SimpleColorPick#__onPreviewColor\n     * @param  {Event} arg0 - 事件信息\n     * @return {Void}\n     */\n    _pro.__onPreviewColor = function(_event){\n        var _element = _v._$getElement(_event,'d:value');\n        if (!_element) return;\n        this.__doPreviewColor(\n            _e._$dataset(_element,'value')\n        );\n    };\n    /**\n     * 预览颜色\n     *\n     * @protected\n     * @method module:ui/colorpick/simple._$$SimpleColorPick#__doPreviewColor\n     * @param  {String} arg0 - 颜色值\n     * @return {Void}\n     */\n    _pro.__doPreviewColor = function(_color){\n        _e._$setStyle(this.__nprv,'backgroundColor',_color);\n    };\n    /**\n     * 修改颜色\n     *\n     * @protected\n     * @method module:ui/colorpick/simple._$$SimpleColorPick#__doChangeColor\n     * @param  {String} arg0 - 颜色值\n     * @return {Void}\n     */\n    _pro.__doChangeColor = function(_color){\n        this._$dispatchEvent('onselect',{\n            color:_color\n        });\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/colorpick/test/colorpanel.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>colorpanel测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit colorpanel test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<div id=\"colorpanel-box\"></div>\n\t\t<div id=\"colorpanel-box2\"></div>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./colorpanel.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/ui/colorpick/test/colorpanel.test.js",
    "content": "var f = function(){\n\t//定义测试模块\n\tmodule(\"colorpanel\");\n\tvar _  = NEJ.P,\n\t\t_e = _('nej.e'),\n\t\t_p = _('nej.ui');\n\t//开始单元测试\n\t// test('colorpanel',function(){\n\t// \tstop();\n\t// \tvar _cp = _p._$$ColorPanel._$allocate({\n\t// \t\tparent:'colorpanel-box',\n\t// \t\tonchange:function(_color){\n\t// \t\t\tok(true,'设置的颜色为：' + _color);\n\t// \t\t\tstart();\n\t// \t\t}\n\t// \t});\n\t// });\n\n\ttest('colorpick',function(){\n\t\tstop();\n\t\texpect(0);\n        var _cp = _p._$$ColorPick._$allocate({\n\t\t\tparent:'colorpanel-box2',\n            onchange:function(_color){\n                // ok(true,'设置的颜色为：' + _color);\n            },\n\t\t\tonselect:function(_color){\n\t\t\t\t// ok(true,'最后设置的颜色为：' + _color);\n\t\t\t\tstart();\n\t\t\t}\n        });\n\t\t_cp._$setColor('#00ff00');\n\t});\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n\tdefine('{pro}colorpanel.test.js',['ui/colorpick/colorpick'],f);\n});"
  },
  {
    "path": "src/ui/datepick/datepick.css",
    "content": ".#<uispace>{width:210px;border:1px solid #aaa;font-size:14px;text-align:center;}\n.#<uispace> .zact{line-height:30px;overflow:hidden;zoom:1;}\n.#<uispace> .zact .zfl{float:left;}\n.#<uispace> .zact .zfr{float:right;}\n.#<uispace> .zact .zbtn{padding:0 5px;cursor:pointer;}\n.#<uispace> .zact .ztxt{margin-left:10px;}\n.#<uispace> .zday{table-layout:fixed;border-collapse:collapse;width:100%;}\n.#<uispace> .zday th{font-weight:normal;}\n.#<uispace> .zday a{display:block;height:22px;line-height:22px;color:#333;text-decoration:none;}\n.#<uispace> .zday a:hover{background:#eee;}\n.#<uispace> .zday a.js-extended{color:#aaa;}\n.#<uispace> .zday a.js-selected,\n.#<uispace> .zday a.js-selected:hover{background:#DAE4E7;}\n.#<uispace> .zday a.js-disabled,\n.#<uispace> .zday a.js-disabled:hover{background:#fff;color:#eee;cursor:default;}"
  },
  {
    "path": "src/ui/datepick/datepick.html",
    "content": "<textarea name='jst' id='#<seedDate>'>\n\t<table class=\"zday\">\n\t\t<tr>{list [\"日\",\"一\",\"二\",\"三\",\"四\",\"五\",\"六\"] as x}<th>${x}</th>{/list}</tr>\n\t\t{list 1..6 as x}\n\t\t<tr>{list 1..7 as y}<td><a href=\"javascript:void(0);\" class=\"js-ztag\"></a></td>{/list}</tr>\n\t\t{/list}\n    </table>\n</textarea>\n\n<textarea name='txt' id='#<seedAction>'>\n\t<div class=\"zact\">\n\t\t<span class=\"zbtn zfl\" title=\"上一年\">&lt;&lt;</span>\n\t\t<span class=\"zbtn zfl\" title=\"上一月\">&lt;</span>\n\t\t<span class=\"zbtn zfr\" title=\"下一年\">&gt;&gt;</span>\n\t\t<span class=\"zbtn zfr\" title=\"下一月\">&gt;</span>\n\t\t<span class=\"ztxt\"></span>年\n\t\t<span class=\"ztxt\"></span>月\n\t</div>\n</textarea>"
  },
  {
    "path": "src/ui/datepick/datepick.js",
    "content": "/*\n * ------------------------------------------\n * 日期选择控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/datepick/datepick */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/util',\n    'ui/layer/card.wrapper',\n    'util/calendar/calendar',\n    'util/template/tpl',\n    'util/template/jst',\n    'text!./datepick.css',\n    'text!./datepick.html'\n],function(NEJ,_k,_e,_u,_i0,_t0,_t1,_t2,_css,_html,_p,_o,_f,_r){\n    var _pro,\n        _seed_html,\n        _seed_css = _e._$pushCSSText(_css),\n        _seed_ui = _t1._$parseUITemplate(_html),\n        _seed_date = _seed_ui['seedDate'],\n        _seed_action = _seed_ui['seedAction'];\n    /**\n     * 日期选择控件\n     *\n     * 页面结构举例\n     * ```html\n     * <style>\n     *     // 注意，样式的优先级\n     *     // 扩展 < 当前 < 禁止\n     *     #datepick-box .js-extended{background:green;}\n     *     #datepick-box .js-selected{background:yellow;}\n     *     #datepick-box .js-disabled{background:red;}\n     * </style>\n     * <div id=\"datepick-box\"></div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/element',\n     *     'ui/datepick/datepick'\n     * ],function(_e,_i0,_p,_o,_f,_r){\n     *     var pDate = new Date(1997,7,9)\n     *     var nDate = new Date(2013,7,9);\n     *     var _dp = _i0._$$DatePick._$allocate({\n     *         parent:_e._$get('datepick-box'),\n     *         // 默认选中日期\n     *         date:'2012-10-10',\n     *         // 设置日期的可选范围\n     *         range:[pDate,nDate],\n     *         onchange:function(_date){\n     *             // 选择了一个日期，返回此日期\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @class     module:ui/datepick/datepick._$$DatePick\n     * @uses      module:util/calendar/calendar._$$Calendar\n     * @extends   module:ui/layer/card._$$CardWrapper\n     * @param     {Object} arg0  - 可选配置参数\n     * @property  {Date}   date  - 设置日期\n     * @property  {Array}  range - 可选范围\n     */\n    /**\n     * 日期变化触发事件\n     *\n     * @event  module:ui/datepick/datepick._$DatePick#onchange\n     * @param  {Date} arg0 - 日期\n     *\n     */\n    _p._$$DatePick = _k._$klass();\n    _pro = _p._$$DatePick._$extend(_i0._$$CardWrapper);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:ui/datepick/datepick._$$DatePick#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__copt = {\n            onselect:this.__onDateChange._$bind(this)\n        };\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/datepick/datepick._$$DatePick#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__copt.range = _options.range;\n        this.__calendar = _t0._$$Calendar\n                            ._$allocate(this.__copt);\n        this._$setDate(_options.date||(new Date()));\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/datepick/datepick._$$DatePick#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__copt.range;\n        var _calendar = this.__calendar;\n        if (!!_calendar){\n            delete this.__calendar;\n            _calendar._$recycle();\n        }\n    };\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/datepick/datepick._$$DatePick#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css  = _seed_css;\n        this.__seed_html = _seed_html;\n    };\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method module:ui/datepick/datepick._$$DatePick#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        var _list = _e._$getChildren(this.__body);\n        this.__copt.list = _e._$getByClassName(_list[1],'js-ztag');\n        _list = _e._$getChildren(_list[0]);\n        this.__copt.yprv = _list[0];\n        this.__copt.mprv = _list[1];\n        this.__copt.ynxt = _list[2];\n        this.__copt.mnxt = _list[3];\n        this.__copt.year = _list[4];\n        this.__copt.month= _list[5];\n    };\n    /**\n     * 动态构建控件节点模板\n     *\n     * @protected\n     * @method module:ui/datepick/datepick._$$DatePick#__initNodeTemplate\n     * @return {Void}\n     */\n    _pro.__initNodeTemplate = function(){\n        _seed_html = _t1._$addNodeTemplate(\n            '<div class=\"'+_seed_css+' zcard\">'+\n               _t1._$getTextTemplate(_seed_action)+\n               _t2._$get(_seed_date)+\n            '</div>'\n        );\n        this.__seed_html = _seed_html;\n    };\n    /**\n     * 日期变化回调函数\n     *\n     * @protected\n     * @method module:ui/datepick/datepick._$$DatePick#__onDateChange\n     * @param  {Date} arg0 - 日期\n     * @return {Void}\n     */\n    _pro.__onDateChange = function(_date){\n        try{\n            this._$dispatchEvent('onchange',_date);\n        }catch(e){\n            // ignore\n        }\n        // this._$hide();\n        // fix ie8-10 not clear active state for anchors\n        window.setTimeout(\n            this._$hide._$bind(this),0\n        );\n    };\n    /**\n     * 设置日期\n     *\n     * 脚本举例\n     * ```javascript\n     * _dp._$setDate('2012-12-21');\n     * ```\n     *\n     * @method module:ui/datepick/datepick._$$DatePick#_$setDate\n     * @param  {Date} arg0 - 日期\n     * @return {Void}\n     */\n    _pro._$setDate = function(_date){\n        _date = _u._$var2date(_date);\n        this.__calendar._$setDate(_date);\n    };\n    /**\n     * 取当前时间\n     *\n     * 脚本举例\n     * ```javascript\n     * // 返回一个Date对象\n     * var _date = _dp._$getDate();\n     * ```\n     *\n     * @method module:ui/datepick/datepick._$$DatePick#_$getDate\n     * @return {Date} 日期\n     */\n    _pro._$getDate = function(){\n        return this.__calendar._$getDate();\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/datepick/demo/datepick.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>demo for colorpick</title>\n    <meta charset=\"utf-8\" />\n    <style>\n        #test-page a:active{color:#f00;background:#0C32F6;}\n    </style>\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n  </head>\n  <body id=\"test-page\">\n    <input type=\"button\" value=\"show\" id=\"abc\"/>\n    <script src=\"../../../define.js\"></script>\n    <script>\n      NEJ.define([\n          'base/event',\n          '../datepick.js'\n      ],function(v,_i){\n          _i._$$DatePick._$attach('abc',{\n              date:new Date,\n              destroyable:true,\n              range:[new Date(2015,10,16,0,0,0),new Date('2016-11-26')],\n              onchange:function(_date){\n                  log('select date -> '+_date);\n              },\n              onbeforerecycle:function(){\n                  log('recycle');\n              }\n          });\n\n//\n//\n//          var x;\n//          v._$addEvent('abc','click',function(ev){\n//              v._$stop(ev);\n//              if (!x){\n//                  x = _i._$$DatePick._$allocate({\n//                      parent:document.body,\n//                      date:new Date,\n//                      range:[new Date(2015,10,16,0,0,0),new Date('2016-11-26')],\n//                      onchange:function(_date){\n//                          log('select date -> '+_date);\n//                      },\n//                      onbeforerecycle:function(){\n//                          x = null;\n//                      }\n//                  });\n//              }else{\n//                  x._$show();\n//              }\n//          });\n\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/ui/datepick/test/datepick.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>datepick测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style type=\"text/css\">\n\t\t\t#datepick-box  .js-extended{background:green;}\n\t\t\t#datepick-box  .js-selected{background:yellow;}\n            #datepick-box  .js-disabled{background:red;}\n            #datepick-box2 .js-extended{background:green;}\n            #datepick-box2 .js-selected{background:yellow;}\n            #datepick-box2 .js-disabled{background:red;}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit datepick test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<div id=\"datepick-box\"></div>\n\t\t<div id=\"datepick-box2\">\n\t\t\t<div id=\"days\"></div>\n\t\t\t<div id=\"year\"></div>\n\t\t\t<div id=\"month\"></div>\n\t\t\t<div id=\"yprv\">前一年</div>\n\t\t\t<div id=\"mprv\">前一月</div>\n\t\t\t<div id=\"ynxt\">后一年</div>\n\t\t\t<div id=\"mnxt\">后一月</div>\n\t\t</div>\n\t\t<div id=\"datepick\">jjjjjjjjjjjjj</div>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./datepick.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/ui/datepick/test/datepick.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"datepick\");\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _p = _('nej.ui'),\n        _ut= _('nej.ut');\n\n\n    //开始单元测试\n    test('datepick-ui',function(){\n        stop();\n        var _dp = _p._$$DatePick._$allocate({\n            parent:_e._$get('datepick-box'),\n            onchange:function(_date){\n                ok(true,'选择了一个日期，返回此日期'+_date);\n                start();\n            }\n        });\n\t\t_dp._$setDate('2012-12-21');\n\t\t_dp._$getDate();\n    });\n\n    test('datepick-util',function(){\n        expect(0);\n        var pDate = new Date(1997,7,9)\n        var nDate = new Date(2013,7,9);\n        var _days = _e._$get('days');\n        _html = _e._$add('{list 1..2 as x}<div>{list 1..6 as y}<p class=\"z-day\"></p>{/list}</div>{/list}');\n        _days.innerHTML = _e._$get(_html);\n        var _dp = _ut._$$Calendar._$allocate({\n            parent:_e._$get('datepick-box2'),\n            offset:1,\n            list:_e._$getByClassName(_days,\"z-day\"),\n            year:_e._$get('year'),\n            month:_e._$get('month'),\n            yprv:_e._$get('yprv'),\n            mprv:_e._$get('mprv'),\n            ynxt:_e._$get('ynxt'),\n            mnxt:_e._$get('mnxt'),\n            onchange:function(_date){\n                // ok(true,'日期变化'+_date);\n                // start();\n            },\n            onselect:function(_date){\n\t\t\t\t_dp._$setDate(_date)\n                // ok(true,'直接用calendar选择了一个日期，返回此日期'+_date);\n                // start();\n            },\n            range:[pDate,nDate]\n        });\n\t\t_dp._$setDate('1998-09-03');\n\t\t_dp._$getDate();\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}datepick.test.js',['ui/datepick/datepick'],f);\n});"
  },
  {
    "path": "src/ui/editor/command/color.complex.js",
    "content": "// link to ui/editor/command/complex for compatible\n// use ui/editor/command/complex for new project\nNEJ.define(['./complex.js'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/editor/command/color.css",
    "content": ".#<uispace>{width:160px;padding:10px 5px 5px;border:1px solid #9FAC87;}"
  },
  {
    "path": "src/ui/editor/command/color.js",
    "content": "/*\n * ------------------------------------------\n * 颜色选择卡片实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/editor/command/color */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'ui/layer/card.wrapper',\n    'ui/colorpick/colorpick',\n    'text!./color.css'\n],function(NEJ,_k,_e,_i0,_i1,_css,_p,_o,_f,_r){\n    var _pro,\n        _seed_css = _e._$pushCSSText(_css);\n    /**\n     * 颜色选择卡片\n     *\n     * @class    module:ui/editor/command/color._$$ColorCard\n     * @extends  module:ui/layer/wrapper/card._$$CardWrapper\n     * @param    {Object} arg0  - 可选配置参数\n     * @property {String} color - 颜色值\n     */\n    /**\n     * 颜色选中回调函数\n     *\n     * @event  module:ui/editor/command/color._$$ColorCard#onchange\n     * @param  {String} color - 颜色值\n     *\n     */\n    _p._$$ColorCard = _k._$klass();\n    _pro = _p._$$ColorCard._$extend(_i0._$$CardWrapper);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:ui/editor/command/color._$$ColorCard#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__copt = {\n            onselect:this.__onColorSelect._$bind(this)\n        };\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/editor/command/color._$$ColorCard#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__copt.color = _options.color;\n        this.__copt.parent = this.__layer._$getBody();\n        this.__copt.defaultColor = _options.defaultColor;\n        this.__colorpick = this.__getColorPicker();\n    };\n    /**\n     * 控件回收\n     *\n     * @protected\n     * @method module:ui/editor/command/color._$$ColorCard#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        if (!!this.__colorpick){\n            this.__colorpick._$recycle();\n            delete this.__colorpick;\n        }\n        delete this.__copt.parent;\n        this.__super();\n    };\n    /**\n     * 取取色器实例\n     *\n     * @protected\n     * @method module:ui/editor/command/color._$$ColorCard#__getColorPicker\n     * @return {Void}\n     */\n    _pro.__getColorPicker = function(){\n        this.__copt.clazz = _seed_css;\n        return _i1._$$ColorPick._$allocate(this.__copt);\n    };\n    /**\n     * 颜色选择回调\n     *\n     * @protected\n     * @method module:ui/editor/command/color._$$ColorCard#__onColorSelect\n     * @param    {Object} arg0  - 颜色配置\n     * @property {String} color - 颜色值\n     * @return   {Void}\n     */\n    _pro.__onColorSelect = function(_event){\n        this._$dispatchEvent('onchange',_event.color);\n        this._$hide();\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/editor/command/color.simple.js",
    "content": "// link to ui/editor/command/simple for compatible\n// use ui/editor/command/simple for new project\nNEJ.define(['./simple.js'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/editor/command/complex.css",
    "content": ".#<uispace>{width:238px;padding:5px 0 8px;border:1px solid #9FAC87;}"
  },
  {
    "path": "src/ui/editor/command/complex.js",
    "content": "/*\n * ------------------------------------------\n * 颜色选择卡片实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/editor/command/complex */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'ui/editor/command/color',\n    'ui/colorpick/colorpick.complex',\n    'text!./complex.css'\n],function(NEJ,_k,_e,_i0,_i1,_css,_p,_o,_f,_r){\n    var _pro,\n        _seed_css = _e._$pushCSSText(_css);\n    /**\n     * 颜色选择卡片\n     *\n     * @class    module:ui/editor/command/complex._$$ComplexColorCard\n     * @extends  module:ui/editor/command/color._$$ColorCard\n     * @param    {Object} arg0  - 可选配置参数\n     * @property {String} color - 颜色值\n     */\n    /**\n     * 颜色选中回调函数\n     *\n     * @event  module:ui/editor/command/complex._$$ComplexColorCard#onchange\n     * @param  {String} color - 颜色值\n     *\n     */\n    _p._$$ComplexColorCard = _k._$klass();\n    _pro = _p._$$ComplexColorCard._$extend(_i0._$$ColorCard);\n    /**\n     * 取取色器实例\n     *\n     * @protected\n     * @method module:ui/editor/command/complex._$$ComplexColorCard#__getColorPicker\n     * @return {Void}\n     */\n    _pro.__getColorPicker = function(){\n        this.__copt.clazz = _seed_css;\n        return _i1._$$ComplexColorPick._$allocate(this.__copt);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/editor/command/font.css",
    "content": ".#<uispace>{border:1px solid #9FAC87;font-size:12px;text-align:left;}\n.#<uispace> .zitm{display:block;position:relative;margin:1px;outline:none;padding:2px 0 2px 8px;border:1px solid #ddd;color:#000;background-color:#fff;text-decoration:none;}\n.#<uispace> .zitm:hover{background-color:#e5e5e1;text-decoration:none;}\n.#<uispace> .zitm .ztip{position:absolute;top:2px;right:5px;font-size:10px;}"
  },
  {
    "path": "src/ui/editor/command/font.html",
    "content": "{list xlist as x}\n<a class=\"zitm\" hidefocus=\"true\" style=\"${style}:${x.style|default:x.name};\" data-index=\"${x_index}\">\n  ${x.name}\n  {if !!x.tip}<span class=\"ztip\">${x.tip}</span>{/if}\n</a>\n{/list}"
  },
  {
    "path": "src/ui/editor/command/font.js",
    "content": "/*\n * ------------------------------------------\n * 字体字号选择卡片基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/editor/command/font */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'base/util',\n    'ui/layer/card.wrapper',\n    'util/template/jst',\n    'text!./font.css',\n    'text!./font.html'\n],function(NEJ,_k,_e,_v,_u,_i,_t0,_css,_html,_p,_o,_f,_r){\n    var _pro,\n        _seed_css = _e._$pushCSSText(_css),\n        _seed_fnt = _t0._$add(_html);\n    /**\n     * 字体字号选择卡片基类\n     *\n     * @class   module:ui/editor/command/font._$$FontCard\n     * @extends module:ui/layer/wrapper/card._$$CardWrapper\n     * @param   {Object} arg0 - 可选配置参数\n     */\n    /**\n     * 字号/字体选中回调函数\n     *\n     * @event  module:ui/editor/command/font._$$FontCard#onchange\n     * @param  {String} font - 字号/字体\n     *\n     */\n    _p._$$FontCard = _k._$klass();\n    _pro = _p._$$FontCard._$extend(_i._$$CardWrapper);\n    /**\n     * 控件重置\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        if (_options.width!=null){\n            _e._$setStyle(\n                this.__body,'width',\n                _options.width+'px'\n            );\n        }\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/editor/command/font._$$FontCard#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__flist;\n    };\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/editor/command/font._$$FontCard#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css  = _seed_css;\n    };\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method module:ui/editor/command/font._$$FontCard#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        _v._$addEvent(\n            this.__body,'click',\n            this.__onFontSelect._$bind(this)\n        );\n    };\n    /**\n     * 构建字体大小选择列表\n     *\n     * @protected\n     * @method module:ui/editor/command/font._$$FontCard#__doGenFontListXhtml\n     * @param  {Object} arg0 - 字体大小列表信息\n     * @return {Void}\n     */\n    _pro.__doGenFontListXhtml = function(_data){\n        return _t0._$get(_seed_fnt,_data);\n    };\n    /**\n     * 字体大小选择事件\n     *\n     * @protected\n     * @method module:ui/editor/command/font._$$FontCard#__onFontSelect\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onFontSelect = (function(){\n        var _doFilter = function(_node){\n            return !isNaN(parseInt(_e._$dataset(_node,'index')));\n        };\n        return function(_event){\n            var _element = _v._$getElement(_event,_doFilter);\n            if (!_element) return;\n            var _index = parseInt(_e.\n                _$dataset(_element,'index'));\n            this._$dispatchEvent('onchange',\n                this.constructor.list[_index]);\n            this._$hide();\n        };\n    })();\n    /**\n     * 取字体字号提示文字\n     *\n     * @method module:ui/editor/command/font._$$FontCard._$getText\n     * @param  {String} value - 字体/字号\n     * @return {String} 字体/字号\n     */\n    _p._$$FontCard._$getText = function(_value){\n        var _index = _u._$indexOf(this.list,\n            function(_data){\n                return (_data.value||_data.name)==_value;\n            });\n        return (this.list[_index]||_o).name;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/editor/command/fontname.js",
    "content": "/*\n * ------------------------------------------\n * 字体选择控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/editor/command/fontname */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'ui/editor/command/font',\n    'util/template/tpl'\n],function(NEJ,_k,_e,_i0,_t0,_p,_o,_f,_r){\n    var _pro,\n        _seed_html;\n    /**\n     * 字体选择控件\n     *\n     * @class   module:ui/editor/command/fontname._$$FontNameCard\n     * @extends module:ui/editor/command/font._$$FontCard\n     * @param   {Object} arg0 - 可选配置参数\n     */\n    /**\n     * 字体选中回调函数\n     *\n     * @event module:ui/editor/command/fontname._$$FontNameCard#onselect\n     * @param {String} arg0 - 字体\n     *\n     */\n    _p._$$FontNameCard = _k._$klass();\n    _pro = _p._$$FontNameCard._$extend(_i0._$$FontCard);\n    /**\n     * 字体选项列表\n     *\n     * @const {Array} module:ui/editor/command/fontname._$$FontNameCard.list\n     */\n    _p._$$FontNameCard.list =\n      [{name:'宋体'}\n      ,{name:'微软雅黑'}\n      ,{name:'黑体'}\n      ,{name:'楷体'}\n      ,{name:'隶书'}\n      ,{name:'幼圆'}\n      ,{name:'Arial'}\n      ,{name:'Arial Narrow'}\n      ,{name:'Arial Black'}\n      ,{name:'Comic Sans MS'}\n      ,{name:'Courier'}\n      ,{name:'System'}\n      ,{name:'Verdana'}\n      ,{name:'Times New Roman'}];\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/editor/command/fontname._$$FontNameCard#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__super();\n        this.__seed_html = _seed_html;\n    };\n    /**\n     * 动态构建控件节点模板\n     *\n     * @protected\n     * @method module:ui/editor/command/fontname._$$FontNameCard#__initNodeTemplate\n     * @return {Void}\n     */\n    _pro.__initNodeTemplate = function(){\n        _seed_html = _t0._$addNodeTemplate(\n                     '<div class=\"'+this.__seed_css+'\">'\n                     +this.__doGenFontListXhtml({\n                         style:'font-family'\n                        ,xlist:this.constructor.list\n                      })+\n                     '</div>');\n        this.__seed_html = _seed_html;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/editor/command/fontsize.js",
    "content": "/*\n * ------------------------------------------\n * 富媒体编辑器字号选择控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/editor/command/fontsize */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'util/template/tpl',\n    'ui/editor/command/font'\n],function(NEJ,_k,_e,_t0,_u,_p,_o,_f,_r){\n    var _pro,\n        _seed_html;\n    /**\n     * 字号选择控件\n     *\n     * @class   module:ui/editor/command/fontsize._$$FontSizeCard\n     * @extends module:ui/editor/command/font._$$FontCard\n     * @param   {Object} arg0 - 可选配置参数\n     */\n    /**\n     * 字号选中回调函数\n     *\n     * @event module:ui/editor/command/fontsize._$$FontSizeCard#onselect\n     * @param {String} arg0 - 字号\n     *\n     */\n    _p._$$FontSizeCard = _k._$klass();\n    _pro = _p._$$FontSizeCard._$extend(_u._$$FontCard);\n    /**\n     * 字号选项列表\n     * @member {Array}\n     */\n    _p._$$FontSizeCard.list =\n      [{name:'小',style:'x-small',value:1}\n      ,{name:'标准',style:'small',value:2}\n      ,{name:'大',style:'medium',value:3}\n      ,{name:'特大',style:'large',value:4}\n      ,{name:'极大',style:'x-large',value:5}];\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/editor/command/fontsize._$$FontSizeCard#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__super();\n        this.__seed_html = _seed_html;\n    };\n    /**\n     * 动态构建控件节点模板\n     *\n     * @protected\n     * @method module:ui/editor/command/fontsize._$$FontSizeCard#__initNodeTemplate\n     * @return {Void}\n     */\n    _pro.__initNodeTemplate = function(){\n        _seed_html = _t0._$addNodeTemplate(\n                     '<div class=\"'+this.__seed_css+'\">'\n                     +this.__doGenFontListXhtml({\n                         style:'font-size'\n                        ,xlist:this.constructor.list\n                      })+\n                     '</div>');\n        this.__seed_html = _seed_html;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/editor/command/link.css",
    "content": ".#<uispace>{padding:20px 20px 32px 20px;}\n.#<uispace> .u-title{color:#ccc;height:35px;line-height:35px;border-bottom: solid 1px #ccc;}\n.#<uispace> .u-row{margin-bottom:10px;}\n.#<uispace> .u-error{color:red;padding-top:10px;font-size:12px;height:2em;}\n.#<uispace> .u-edit{position: relative;z-index: 101;background: #FAFAFA;border: 1px solid #DFDFDF;-webkit-box-shadow: inset 1px 1px 2px #DFDFDF;-moz-box-shadow: inset 1px 1px 2px #dfdfdf;box-shadow: inset 1px 1px 2px #DFDFDF;}\n.#<uispace> .btn a{border:solid 1px #ccc;padding:5px;}\n.#<uispace> .ipt{display:block;font-size: 14px;position: relative;z-index: 101;line-height:35px;height:35px;width: 290px;resize: none;background: transparent;border: none;color: #444;overflow:hidden;}"
  },
  {
    "path": "src/ui/editor/command/link.html",
    "content": "<div>\n\t<div class=\"u-row f-cb\"><div class=\"u-edit f-cb\"><div class=\"f-fl u-title\">标题</div><input class=\"f-fl ipt\" type=\"text\" /></div></div>\n\t<div class=\"f-cb\"><div class=\"u-edit f-cb\"><div class=\"f-fl u-title\">链接</div><input class=\"f-fl ipt\" type=\"text\" value=\"http://\" /></div></div>\n\t<div class=\"u-error j-error\"></div>\n\t<div class=\"btn f-cb\">\n\t  <a class=\"f-fr slave j-btn\"><span>取消 </span></a>\n\t  <a class=\"f-fr main right j-btn\"><span>确定 </span></a>\n\t</div>\n</div>"
  },
  {
    "path": "src/ui/editor/command/link.js",
    "content": "/*\n * ------------------------------------------\n * 超链接卡片实现文件\n * @version  1.0\n * @author   cheng-lin(cheng-lin@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/editor/command/link */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/util',\n    'ui/layer/window.wrapper',\n    'util/template/tpl',\n    'text!./link.css',\n    'text!./link.html'\n],function(NEJ,_k,_e,_u,_i,_t0,_css,_html,_p,_o,_f,_r){\n    var _pro,\n        _seed_html = _t0._$addNodeTemplate(_html),\n        _seed_css = _e._$pushCSSText(_css);\n    /**\n     * 超链接卡片\n     *\n     * @class    module:ui/editor/command/link._$$LinkCard\n     * @extends  module:ui/layer/wrapper/window._$$CardWrapper\n     * @param    {Object}  arg0 - 可选配置参数\n     * @property {Boolean} draggable   - 是否可拖动\n     * @property {Boolean} destroyable - 关闭是否销毁\n     * @property {String}  title       - 卡片标题\n     * @property {Boolean} name        - 超链接名称\n     */\n    /**\n     * 超链接地址有误\n     *\n     * @event module:ui/editor/command/link._$$LinkCard#onErrorLink\n     * @param {Number} arg0 - 错误码\n     * | 错误码| 含义              |\n     * | :---  | :---              |\n     * | 0     | 不是以http://开头 |\n     * | 1     | 地址中有空白字符  |\n     */\n    /**\n     * 超链接通过检验\n     *\n     * @event module:ui/editor/command/link._$$LinkCard#onchange\n     * @param {String} arg0 - 超链接地址\n     *\n     */\n    _p._$$LinkCard = _k._$klass();\n    _pro = _p._$$LinkCard._$extend(_i._$$WindowWrapper);\n\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/editor/command/link._$$LinkCard#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css  = _seed_css;\n        this.__seed_html = _seed_html;\n    };\n\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method module:ui/editor/command/link._$$LinkCard#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        this.__btns = _e._$getByClassName(this.__body,'j-btn');\n        this.__inputs = _e._$getByClassName(this.__body,'ipt');\n        this.__errorMsg = _e._$getByClassName(this.__body,'j-error')[0];\n    };\n\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method   module:ui/editor/command/link._$$LinkCard#__reset\n     * @param    {Object}  arg0        - 可选配置参数\n     * @property {Boolean} draggable   - 是否可拖动\n     * @property {Boolean} destroyable - 关闭是否销毁\n     * @property {String}  title       - 卡片标题\n     * @property {Boolean} name        - 超链接名称\n     * @return   {Void}\n     */\n    _pro.__reset = function(_options){\n        //默认以document为parent\n        _options.parent = _options.parent || document.body;\n        _options.draggable = _options.draggable || false;\n        _options.destroyable = _options.destroyable || false;\n        _options.title = _options.title || '超链接';\n        _options.mask  = _options.maskclazz || true;\n        this.__super(_options);\n        this.__inputs[0].value = _options.name||'';\n        this.__doInitDomEvent([\n            [this.__btns[1],'click',this.__onOK._$bind(this)],\n            [this.__btns[0],'click',this.__onCancel._$bind(this)],\n            [this.__inputs[0],'keypress',this.__onKeyPress._$bind(this)],\n            [this.__inputs[1],'keypress',this.__onKeyPress._$bind(this)],\n            [this.__inputs[0],'focus',this.__showErrorTips._$bind(this,'')],\n            [this.__inputs[1],'focus',this.__showErrorTips._$bind(this,'')]\n        ]);\n    };\n\n    /**\n     * 取消\n     *\n     * @protected\n     * @method module:ui/editor/command/link._$$LinkCard#__onCancel\n     * @return {Void}\n     */\n    _pro.__onCancel = function(){\n        this._$hide();\n    };\n\n    /**\n     * 完成链接\n     *\n     * @protected\n     * @method module:ui/editor/command/link._$$LinkCard#__onOK\n     * @return {Void}\n     */\n    _pro.__onOK = (function(){\n        var _reg = /^(?:http(s)?:\\/\\/)[^\\s].?/,\n            _reg2 = /^(?:http(s)?:\\/\\/).*/;\n        return function(){\n            var _link = {};\n            _link.name = _u._$escape(this.__inputs[0].value);\n            _link.href = this.__inputs[1].value;\n            var _flag = _link.href.search(_reg),\n                _flag2= _link.href.search(_reg2);\n            if(_flag2 < 0){\n                this._$dispatchEvent('onErrorLink',0);\n                return;\n            }\n            if(_flag < 0){\n                this._$dispatchEvent('onErrorLink',1);\n                return;\n            }\n            this._$dispatchEvent('onchange',_link);\n            this._$hide();\n        };\n    })();\n\n    /**\n     * 显示错误信息\n     *\n     * @protected\n     * @method module:ui/editor/command/link._$$LinkCard#__showErrorTips\n     * @param  {Object} arg0 - 错误信息\n     * @return {Void}\n     */\n    _pro.__showErrorTips = function(_message){\n        this.__errorMsg.innerText = _message;\n    };\n\n    /**\n     * 控件回收\n     *\n     * @protected\n     * @method module:ui/editor/command/link._$$LinkCard#__destroy\n     * @return {Void}\n     */\n    _pro.__onKeyPress = function(_event){\n        if (_event.keyCode == 13){\n            this.__onOK();\n        }\n    };\n\n    /**\n     * 提供聚焦到input的接口\n     *\n     * @method module:ui/editor/command/link._$$LinkCard#_$doFocus\n     * @return {Void}\n     */\n    _pro._$doFocus = function(){\n        this.__inputs[1].focus();\n        this.__inputs[1].value = 'http://';\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/editor/command/simple.css",
    "content": ".#<uispace>{width:160px;padding:5px 0;border:1px solid #9FAC87;}"
  },
  {
    "path": "src/ui/editor/command/simple.js",
    "content": "/*\n * ------------------------------------------\n * 颜色选择卡片实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/editor/command/simple */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'ui/editor/command/color',\n    'ui/colorpick/colorpick.simple',\n    'text!./simple.css'\n],function(NEJ,_k,_e,_i0,_i1,_css,_p,_o,_f,_r){\n    var _pro,\n        _seed_css = _e._$pushCSSText(_css);\n    /**\n     * 颜色选择卡片\n     *\n     * @class     module:ui/editor/command/simple._$$SimpleColorCard\n     * @extends   module:ui/editor/command/color._$$ColorCard\n     * @param     {Object} arg0  - 可选配置参数\n     * @property  {String} color - 颜色值\n     */\n    /**\n     * 颜色选中回调函数\n     *\n     * @event  module:ui/colorpick/colorpanel._$$ColorPanel#onchange\n     * @param  {String} arg0 - 颜色值\n     *\n     */\n    _p._$$SimpleColorCard = _k._$klass();\n    _pro = _p._$$SimpleColorCard._$extend(_i0._$$ColorCard);\n    /**\n     * 取取色器实例\n     *\n     * @protected\n     * @method module:ui/editor/command/simple._$$SimpleColorCard#__initXGui\n     * @return {Void}\n     */\n    _pro.__getColorPicker = function(){\n        this.__copt.clazz = _seed_css;\n        return _i1._$$SimpleColorPick._$allocate(this.__copt);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/editor/command/uploadimage.css",
    "content": ".#<uispace>{width:336px;}\n.#<uispace> .m-iframe{position:absolute;height:0px;width:0px;left:-9000px;}\n.#<uispace> .u-upload-file{height:0px;width:0px;font-size:0px;}\n.#<uispace> .u-error{color:red;padding-top:10px;}\n.#<uispace> .choose_file{position:relative;margin-bottom:10px;}\n.#<uispace> .choose_file object{position:absolute;left:0;top:0;}\n.#<uispace> .web_img{margin-bottom:8px;}\n.#<uispace> .web_img .u-edit{margin-bottom:10px;}\n.#<uispace> .u-desc{color:#ccc;}\n.#<uispace> .middle{color:#528CE0;}\n.#<uispace> .u-btn{cursor:pointer;color:#528CE0;}\n.#<uispace> .u-image{width:0px;height:0px;visibility:hidden;}"
  },
  {
    "path": "src/ui/editor/command/uploadimage.html",
    "content": "<div>\n\t<div>\n\t  <a class=\"u-btn f-ib upload j-tab f-fl\" name=\"upload\"><span class=\"img-upload\">上传图片</span></a>\n\t  <a class=\"u-btn f-ib extern j-tab\" name=\"extern\"><span class=\"img-extern\">引用站外图片</span></a>\n\t  <img class=\"j-ztag u-image\" />\n\t</div>\n\t<div class=\"j-cnt\">\n\t  <div class=\"choose_file\" name=\"select_image\">\n\t    <div class=\"btn2\">\n\t      <a class=\"main middle\"><span>选择图片</span></a>\n\t    </div>\n\t  </div>\n\t  <p class=\"u-desc j-desc\"></p>\n\t</div>\n\t<div class=\"j-cnt\">\n\t  <div class=\"f-cb web_img\">\n\t      <div class=\"f-fl u-edit\"><input class=\"ipt j-ztag\" type=\"text\" /></div>\n\t      <div class=\"btn2 f-fl j-ztag\">\n\t        <a class=\"main small\"><span>确定</span></a>\n\t      </div>\n\t  </div>\n\t  <p class=\"u-desc j-desc\"></p>\n\t</div>\n\t<div class=\"u-error j-ztag\"></div>\n</div>"
  },
  {
    "path": "src/ui/editor/command/uploadimage.js",
    "content": "/*\n * ------------------------------------------\n * 富媒体编辑器图片上传控件实现文件\n * @version  1.0\n * @author   cheng-lin(cheng-lin@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/editor/command/uploadimage */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/config',\n    'base/element',\n    'base/event',\n    'base/util',\n    'ui/layer/window.wrapper',\n    'util/tab/tab',\n    'util/flash/flash',\n    'util/template/tpl',\n    'text!./uploadimage.css',\n    'text!./uploadimage.html'\n],function(NEJ,_k,_c,_e,_v,_u,_i0,_t0,_t1,_t2,_css,_html,_p,_o,_f,_r){\n    var _pro,\n        _seed_css = _e._$pushCSSText(_css),\n        _seed_html = _t2._$addNodeTemplate(_html);\n    /**\n     * 图片上传控件\n     *\n     * @class     module:ui/editor/command/uploadimage._$$UploadImageCard\n     * @uses      module:util/tab/tab._$$Tab\n     * @extends   module:ui/layer/wrapper/window._$$WindowWrapper\n     * @param     {Object}      arg0           -  可选配置参数\n     * @property  {String|Node} parent         -  父容器\n     * @property  {Boolean}     draggable      -  是否可拖拽\n     * @property  {Boolean}     destroyable    -  关闭是否销毁\n     * @property  {String}      title          -  卡片标题\n     * @property  {String}      fDesc          -  自定义错误提示1\n     * @property  {String}      oDesc          -  自定义错误提示2\n     * @property  {String}      swfUrl         -  Flash文件路径\n     * @property  {String}      baseUrl        -  Flash文件路径的前缀\n     * @property  {Number}      flashWidth     -  Flash宽度\n     * @property  {Number}      flashHeight    -  Flash高度\n     * @property  {String}      userdefinesize - 图片尺寸，默认750x750x0x90;350x350x0x85\n     * @property  {String}      saveorigin     -  是否保存源文件,默认false\n     * @property  {String}      responsetype   -  响应格式,默认xml\n     * @property  {String}      rotatedegree   -  旋转角度，默认0\n     * @property  {String}      stamptype      -  水印类型，默认无\n     * @property  {String}      stampstring    -  水印内容，默认无\n     * @property  {String}      sitefrom       -  产品名称\n     */\n    /**\n     * Flash开始初始化\n     *\n     * @event  module:ui/editor/command/uploadimage._$$UploadImageCard#oninitflash\n     */\n    /**\n     * Flash初始化完成\n     *\n     * @event  module:ui/editor/command/uploadimage._$$UploadImageCard#onflashinited\n     */\n    /**\n     * 图片上传完成\n     *\n     * @event  module:ui/editor/command/uploadimage._$$UploadImageCard#onchange\n     * @param  {String} arg0 - 命令名称\n     * @param  {Object} arg1 - Flash返回的图片对象\n     *\n     */\n    _p._$$UploadImageCard = _k._$klass();\n    _pro = _p._$$UploadImageCard._$extend(_i0._$$WindowWrapper);\n\n    /**\n     * 重置卡片\n     *\n     * @protected\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__reset\n     * @param  {Object} arg0 - 可配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        _options = _options || {};\n        _options.parent = _options.parent || document.body; //默认以document为parent\n        _options.draggable = _options.draggable || false;\n        _options.destroyable = _options.destroyable || false;\n        _options.title = _options.title || '选择图片';\n        _options.mask  = true;\n        this.__super(_options);\n        this.__onShowErrorTips('');\n    };\n\n    /**\n     * 初始化卡片\n     *\n     * @protected\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__init\n     * @param  {Object} arg0 - 可配置参数\n     * @return {Void}\n     */\n    _pro.__init = function(_options){\n        _options = _options||{};\n        this.__super(_options);\n        this.__desc[0].innerText = _options.fDesc || '支持JPG、JPEG、GIF、BMP格式的图片，文件需小于10M';\n        this.__desc[1].innerText = _options.oDesc || '网络图片不能超过2M';\n        this._$setEvent('oninitflash',_options.oninitflash || _f);\n        this._$setEvent('onflashinited',_options.onflashinited || _f);\n        this._$dispatchEvent('oninitflash');\n        this.__doRegiestFlashEvent(_options.namespace || 'nej.ui.cmd');\n        var _url = encodeURIComponent(_options.baseUrl || \"http://upload.photo.163.com/anony/web/upload/userdefinesize?\"+\n                          + \"userdefinesize=\" + _options.userdefinesize || '750x750x0x90;350x350x0x85'\n                          + \"&saveorigin=\" + _options.saveorigin || 'false'\n                          + \"&responsetype=\" + _options.responsetype || 'xml'\n                          + \"&rotatedegree=\" + _options.rotatedegree || '0'\n                          + \"&stamptype=\" + _options.stamptype || ''\n                          + \"&stampstring=\" + encodeURIComponent(_options.stampstring || '')\n                          + \"&sitefrom=\" + _options.sitefrom || 'study');\n        this.__hopt = {\n            src: _options.swfUrl || _c._$get('upload.image.swf'),\n            hidden: false,\n            parent: _e._$getByClassName(this.__body,'choose_file')[0],\n            width: _options.flashWidth || 100,\n            height: _options.flashHeight || 20,\n            params: {\n                flashvars: 'cbNameSpace=' + this.__namespace + '&uploadExif=true&uploadUrl=' + _url,\n                allowscriptaccess: 'always',\n                wmode: 'transparent'\n            },\n            onready: this.__onFlashReady._$bind(this)\n        };\n        _t1._$flash(this.__hopt);\n    };\n\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        this.__desc = _e._$getByClassName(this.__body,'j-desc');\n        // 0 : 图片上传模式1\n        // 1 ：图片上传模式2\n        this.__cnts = _e._$getByClassName(this.__body,'j-cnt');\n        var _nlist = _e._$getByClassName(this.__body,'j-ztag');\n        // 0 : 检查网络图片的容器\n        // 1 : 图片url\n        // 2 : 确认按钮\n        // 3 : 错误提示节点\n        this.__nimgUrl = _nlist[1];\n        this.__nerrorMsg = _nlist[3];\n        this.__nimgBox = _nlist[0];\n        this.__topt = {\n            list:_e._$getByClassName(this.__body,'j-tab'),\n            selected:'j-selected',\n            onchange:this.__onTabChange._$bind(this)\n        };\n        this.__tabMg = _t0._$$Tab._$allocate(this.__topt);\n        _v._$addEvent(_nlist[2],'click',this.__onSubmitImgUrl._$bind(this));\n        _v._$addEvent(this.__nimgBox,'error',this.__onImgUrlError._$bind(this));\n        _v._$addEvent(this.__nimgBox,'load',this.__onImgLoad._$bind(this));\n        _v._$addEvent(this.__nimgUrl,'focus',this.__onShowErrorTips._$bind(this,''));\n    };\n\n    /**\n     * 动态构建控件节点模板\n     *\n     * @protected\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__initNodeTemplate\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css = _seed_css;\n        this.__seed_html = _seed_html;\n    };\n\n    /**\n     * 注册flash回调方法\n     *\n     * @protected\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__doRegiestFlashEvent\n     * @param  {String} arg0 - Flash回调方法的命名空间\n     * @return {Void}\n     */\n    _pro.__doRegiestFlashEvent = function(_space){\n        this.__namespace = _space + _u._$randNumberString(2);\n        var _namespace = NEJ.P(this.__namespace);\n        _namespace.uploadStart = this.__onUploadStart._$bind(this);\n        _namespace.uploadComplete = this.__onUploadComplete._$bind(this);\n        _namespace.uploadError = this.__uploadError._$bind(this);\n        _namespace.showProgress = this.__showProgress._$bind(this);\n    };\n\n    /**\n     * 图片上传完成的回调\n     *\n     * @protected\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onUploadComplete\n     * @param  {Number} id       - flash的操作id\n     * @param  {String} code     - 图片上传状态码\n     * @param  {Object} photoObj - 相册返回的图片对象\n     * @return {Void}\n     */\n    _pro.__onUploadComplete = function(_id,_code,_photoObj){\n        if(_code != 999){\n            this.__onShowErrorTips('图片上传失败');\n        }else{\n            this.__onShowErrorTips('');\n            this._$dispatchEvent('onchange','inserthtml',_photoObj);\n            this.__onafterupload();\n            this._$hide();\n        }\n    };\n\n    /**\n     * 上传图片出错信息设置\n     *\n     * @protected\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onShowErrorTips\n     * @param  {String} arg0 - 错误信息\n     * @return {Void}\n     */\n    _pro.__onShowErrorTips = function(_message){\n        this.__nerrorMsg.innerText = _message;\n    };\n\n    /**\n     * 开始图片上传\n     *\n     * @protected\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onUploadStart\n     * @return {Void}\n     */\n    _pro.__onUploadStart = function(){\n        this.__onbeforeupload();\n    };\n\n    /**\n     * flash加载完成回调\n     *\n     * @protected\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onFlashReady\n     * @param  {Object} arg0 - Flash对象\n     * @return {Void}\n     */\n    _pro.__onFlashReady = function(_flash){\n        this.__flashObj = _flash;\n        this._$dispatchEvent('onflashinited');\n    };\n\n    /**\n     * 提交网络图片\n     *\n     * @protected\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onSubmitImgUrl\n     * @return {Void}\n     */\n    _pro.__onSubmitImgUrl = function(){\n        this.__nimgBox.src = this.__nimgUrl.value.trim();\n    };\n\n    /**\n     * 图片链接错误\n     *\n     * @protected\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onImgUrlError\n     * @return {Void}\n     */\n    _pro.__onImgUrlError = function(){\n        if (this.__nimgBox.src.indexOf('htpp://false')>0){\n            this.__nerrorMsg.innerText = '无法获取链接中的图片，请检查链接或稍后重试';\n        }\n    };\n\n    /**\n     * 图片链接正确\n     *\n     * @protected\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onImgLoad\n     * @return {Void}\n     */\n    _pro.__onImgLoad = function(){\n        var _photoObj = {\n            resultcode:999,\n            userDef2Url:this.__nimgUrl.value\n        };\n        this.__nimgBox.src = 'htpp://false';\n        this.__onUploadComplete('webimg',_photoObj.resultcode,_photoObj);\n    };\n\n    /**\n     * 图片上传前操作，子类实现\n     *\n     * @abstract\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onbeforeupload\n     * @return {Void}\n     */\n    _pro.__onbeforeupload = _f;\n\n    /**\n     * 图片上传后操作，子类实现\n     *\n     * @abstract\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onafterupload\n     * @return {Void}\n     */\n    _pro.__onafterupload = _f;\n\n    /**\n     * 图片上传错误，子类实现\n     *\n     * @abstract\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__uploadError\n     * @return {Void}\n     */\n    _pro.__uploadError = _f;\n\n    /**\n     * 图片上传进程回调，子类实现\n     *\n     * @abstract\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__showProgress\n     * @return {Void}\n     */\n    _pro.__showProgress = _f;\n\n    /**\n     * 切换tab\n     *\n     * @protected\n     * @method module:ui/editor/command/uploadimage._$$UploadImageCard#__onTabChange\n     * @param  {Object} arg0 - 当前Tab对象\n     * @return {Void}\n     */\n    _pro.__onTabChange = function(_event){\n        this.__onShowErrorTips('');\n        var _index = _event.index;\n        this.__nimgUrl.value = '';\n        _e._$setStyle(this.__cnts[_index],'display','');\n        _e._$setStyle(this.__cnts[(_index+1)%2],'display','none');\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui.cmd'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/ui/editor/custom.js",
    "content": "/*\n * ------------------------------------------\n * 自定义富媒体编辑器封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/editor/custom */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'ui/editor/editor',\n    'util/template/tpl',\n    'util/editor/command/fontsize',\n    'util/editor/command/fontname',\n    'util/editor/command/bold',\n    'util/editor/command/italic',\n    'util/editor/command/insertorderedlist',\n    'util/editor/command/insertunorderedlist',\n    'util/editor/command/underline',\n    'util/editor/command/strikethrough',\n    'util/editor/command/forecolor',\n    'util/editor/command/backcolor',\n    'util/editor/command/justifyleft',\n    'util/editor/command/justifycenter',\n    'util/editor/command/justifyright',\n    'util/editor/command/link',\n    'util/editor/command/format',\n    'util/editor/command/uploadimage',\n    'util/editor/command/blockquote'\n],function(NEJ,_k,_i0,_t0,_t1,_t2,_t3,_t4,_t5,_t6,_t7,_t8,_t9,_t10,_t11,_t12,_t13,_t14,_t15,_t16,_t17,_p,_o,_f,_r){\n    var _pro,\n        _seed_html;\n    /**\n     * 富媒体编辑器封装\n     *\n     * @class   module:ui/editor/custom._$$CustomEditor\n     * @extends module:ui/editor/editor._$$Editor\n     * @param   {Object} arg0 - 可选配置参数\n     */\n    _p._$$CustomEditor = _k._$klass();\n    _pro = _p._$$CustomEditor._$extend(_i0._$$Editor);\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/editor/custom._$$CustomEditor#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__super();\n        this.__seed_html = _seed_html;\n    };\n    /**\n     * 动态构建控件节点模板\n     *\n     * @protected\n     * @method module:ui/editor/custom._$$CustomEditor#__initNodeTemplate\n     * @return {Void}\n     */\n    _pro.__initNodeTemplate = (function(){\n        var _flist = [{cmd:'bold',txt:'加粗',icn:'z-i-30'}\n                     ,{cmd:'italic',txt:'斜体',icn:'z-i-31'}\n                     ,{cmd:'underline',txt:'下划线',icn:'z-i-32'}\n                     ,{cmd:'strikethrough',txt:'删除线',icn:'z-i-40'}\n                     ,{cmd:'insertorderedlist',txt:'有序列表',icn:'z-i-61'}\n                     ,{cmd:'insertunorderedlist',txt:'无序列表',icn:'z-i-62'}\n                     ,{cmd:'foreColor',txt:'字体颜色',icn:'z-i-41'}\n                     ,{cmd:'hiliteColor',txt:'背景颜色',icn:'z-i-122'}],\n            _tlist = [{cmd:'justifyLeft',txt:'左对齐',icn:'z-i-50'}\n                     ,{cmd:'justifyCenter',txt:'居中对齐',icn:'z-i-51'}\n                     ,{cmd:'justifyRight',txt:'右对齐',icn:'z-i-52'}\n                     ,{cmd:'link',txt:'超链接',icn:'z-i-42'}\n                     ,{cmd:'format',txt:'清除格式',icn:'z-i-72'}\n                     ,{cmd:'uploadImage',txt:'照片上传',icn:'z-i-82'}];\n        return function(){\n            _seed_html = _t0._$addNodeTemplate(\n                this.__doGenEditorXhtml({\n                    toolbar:this.__doGenFontSizeXhtml()\n                           +this.__doGenFontNameXhtml()\n                           +this.__doGenCmdXhtml({xlist:_flist,hr:!0})\n                           +this.__doGenCmdXhtml({xlist:_tlist})\n                }));\n            this.__seed_html = _seed_html;\n        };\n    })();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/editor/demo/custom.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test editor</title>\n    <meta charset=\"utf-8\"/>\n      <style>\n          div.m-abc{width:800px;height:400px;}\n      </style>\n\n  </head>\n  <body>\n    <script>window.NEJ_CONF={root:'../../../../res/'};</script>\n    <script src=\"../../../define.js\"></script>\n    <script>\n      define([\n          'base/event',\n          '../custom.js'\n      ],function(_v,_i){\n          var editor = _i._$$CustomEditor._$allocate({\n              parent:document.body,\n              clazz:'m-abc'\n          });\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/ui/editor/editor.css",
    "content": ".#<uispace>{width:500px;border:1px solid #ddd;text-align:center;}\n.#<uispace> .zbg{background:url(#<root>nej_editor.png?20131028) no-repeat 100px 100px;}\n.#<uispace> .ztbar{height:30px;background-color:#eee;zoom:1;}\n.#<uispace> .ztbar:after{display:block;clear:both;visibility:hidden;height:0;content:\".\";}\n.#<uispace> .zitm{float:left;width:24px;height:24px;margin:3px 0;cursor:pointer;}\n.#<uispace> .zitm:hover{background-position:0 0;}\n.#<uispace> .zitm.js-selected{background-position:-30px 0;}\n.#<uispace> .zitm .zicn{width:16px;height:16px;margin:4px auto 0;overflow:hidden;text-indent:100px;}\n.#<uispace> .zitm .ztxt{display:none;}\n.#<uispace> .zisp{float:left;width:10px;height:24px;margin:3px 0;background-position:-60px 0;overflow:hidden;}\n.#<uispace> .zsel{float:left;position:relative;height:20px;overflow:hidden;line-height:20px;padding:0 5px;margin:4px;border:1px solid #C5C5C5;background:#fff;font-size:12px;text-align:left;cursor:pointer;}\n.#<uispace> .zsel .zarw{position:absolute;top:0;right:0;width:18px;height:18px;background-position:0px -244px;}\n.#<uispace> .zsel.zfs{width:60px;}\n.#<uispace> .zsel.zfm{width:140px;}\n.#<uispace> .zarea{height:200px;}\n.#<uispace> .zarea iframe{width:100%;height:100%;overflow:hidden;}"
  },
  {
    "path": "src/ui/editor/editor.html",
    "content": "<textarea name='jst' id='#<seedIcmd>'>\n{list xlist as x}\n    <div class=\"zitm zbg ${'js-'|seed}\" data-command=\"${x.cmd}\" title=\"${x.txt}\">\n      <div class=\"zicn zbg ${x.icn}\">&nbsp;</div>\n      <div class=\"ztxt\">${x.txt}</div>\n    </div>\n    {/list}\n    {if defined(\"hr\")&&!!hr}\n    <div class=\"zbg zisp\">&nbsp;</div>\n{/if}\n</textarea>\n<textarea name='jst' id='#<seedIfnt>'>\n<div class=\"zsel ${icn} ${'js-'|seed}\" data-command=\"${cmd}\">\n  <span class=\"${'js-t-'|seed}\">${txt}</span>\n  <span class=\"zarw zbg\">&nbsp;</span>\n</div>\n</textarea>\n<textarea name='jst' id='#<seedIedt>'>\n<div>\n  <div class=\"ztbar\">${toolbar}</div>\n  <div class=\"zarea\"></div>\n</div>\n</textarea>"
  },
  {
    "path": "src/ui/editor/editor.js",
    "content": "/*\n * ------------------------------------------\n * 富媒体编辑器基类封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/editor/editor */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/config',\n    'base/element',\n    'base/event',\n    'base/util',\n    'ui/base',\n    'util/editor/editor',\n    'util/template/jst',\n    'util/editor/area',\n    'util/editor/toolbar',\n    'util/template/tpl',\n    'text!./editor.css',\n    'text!./editor.html'\n],function(NEJ,_k,_c,_e,_v,_u,_i,_t0,_t1,_t2,_t3,_t4,_css,_html,_p,_o,_f,_r){\n    var _seed_css,\n        _seed_ui = _t4._$parseUITemplate(_html),\n        _seed_icmd = _seed_ui['seedIcmd'],\n        _seed_ifnt = _seed_ui['seedIfnt'],\n        _seed_iedt = _seed_ui['seedIedt'],\n        _pro;\n    /**\n     * 富媒体编辑器基类封装\n     *\n     * @class     module:ui/editor/editor._$$Editor\n     * @uses      module:util/editor/area._$$EditorArea\n     * @uses      module:util/editor/toolbar._$$EditorToolbar\n     * @extends   module:ui/base._$$Abstract\n     * @param     {Object}  arg0    - 可选配置参数\n     * @property  {Boolean} focus   - 是否自动聚焦\n     * @property  {String}  content - 文本内容\n     *\n     */\n    _p._$$Editor = _k._$klass();\n    _pro = _p._$$Editor._$extend(_i._$$Abstract);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:ui/editor/editor._$$Editor#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__aopt = {};\n        this.__topt = {};\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/editor/editor._$$Editor#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        _u._$merge(this.__aopt,_options,function(_value,_key){\n            if(_key.search(/^on/)<0){\n                return !0;\n            }\n        });\n        this.__aopt.style = _options.style;\n        this.__aopt.content = _options.content;\n        this.__aopt.focus = _options.focus!==!1;\n        this.__editor = _t0._$$Editor._$allocate({\n            area:_t2._$$EditorArea._$allocate(this.__aopt)\n           ,toolbar:_t3._$$EditorToolbar._$allocate(this.__topt)\n        });\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/editor/editor._$$Editor#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        // recycle editor first\n        this.__editor._$recycle();\n        this.__super();\n        delete this.__editor;\n    };\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/editor/editor._$$Editor#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css = _seed_css;\n    };\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method module:ui/editor/editor._$$Editor#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        var _list = _e._$getChildren(this.__body);\n        this.__aopt.parent = _list[1];\n        this.__topt.list = _e._$getByClassName(_list[0],\n                           'js-'+_t1._$seed());\n    };\n    /**\n     * 获取按钮html代码\n     *\n     * @protected\n     * @method module:ui/editor/editor._$$Editor#__doGenCmdXhtml\n     * @param  {Object} arg0 - 命令数据\n     * @return {String} html代码\n     */\n    _pro.__doGenCmdXhtml = function(_data){\n        return _t1._$get(_seed_icmd,_data);\n    };\n    /**\n     * 获取字号选择html代码\n     *\n     * @protected\n     * @method module:ui/editor/editor._$$Editor#__doGenFontSizeXhtml\n     * @return {String} html代码\n     */\n    _pro.__doGenFontSizeXhtml = function(){\n        return _t1._$get(_seed_ifnt,\n               {cmd:'fontSize',txt:'标准',icn:'zfs'});\n    };\n    /**\n     * 获取字体选择html代码\n     *\n     * @protected\n     * @method module:ui/editor/editor._$$Editor#__doGenFontNameXhtml\n     * @return {String} html代码\n     */\n    _pro.__doGenFontNameXhtml = function(){\n        return _t1._$get(_seed_ifnt,\n               {cmd:'fontName',txt:'Arial',icn:'zfm'});\n    };\n    /**\n     * 获取编辑器html代码\n     *\n     * @protected\n     * @method module:ui/editor/editor._$$Editor#__doGenEditorXhtml\n     * @param  {Object} arg0 - 命令数据\n     * @return {Void}\n     */\n    _pro.__doGenEditorXhtml = function(_data){\n        return _t1._$get(_seed_iedt,_data);\n    };\n    /**\n     * 取编辑内容\n     *\n     * @param  {Boolean|Number|Object}  默认过滤所有style(只保留background-color,font-size,color样式)，如果是对象，keepStyle表示不过滤style，noId表示过滤id\n     * @method module:ui/editor/editor._$$Editor#_$getContent\n     * @return {String} 内容\n     */\n    _pro._$getContent = function(_options){\n        return this.__editor._$getContent(_options);\n    };\n    /**\n     * 取编辑内容里的图片id和url列表\n     *\n     * @method module:ui/editor/editor._$$Editor#_$getContent\n     * @return {Array} 编辑内中的图片ID+@+图片地址的列表，根据ID是否为0判断是否需要放入列表\n     */\n    _pro._$getPhotoIdsAndUrls = (function(){\n        var _filter = function(_item){\n            if(_item.id!=0)\n                this.__idsAndUrls.push(_item.id+'@'+_item.src);\n        }\n        return function(){\n            this.__idsAndUrls = [];\n            var _photoIdsAndUrls = [],\n                _content = this.__editor._$getContent(),\n                _div = document.createElement('div');\n            _div.innerHTML = _content;\n            var _document = _e._$get(_div),\n                _list = _document.getElementsByTagName('img');\n            _u._$forEach(_list,_filter,this);\n            var _idsAndUrlsLength = this.__idsAndUrls.length;\n            for(var i = 0; i < _idsAndUrlsLength; i++)\n                _photoIdsAndUrls.push(this.__idsAndUrls[i]);\n            return _photoIdsAndUrls;\n        }\n    })();\n    /**\n     * 取纯文本编辑内容\n     * @method module:ui/editor/editor._$$Editor#_$getTextContent\n     * @return {String} 内容\n     */\n    _pro._$getTextContent = function(){\n        return this.__editor._$getTextContent();\n    };\n    /**\n     * 设置编辑内容\n     * @method module:ui/editor/editor._$$Editor#_$setContent\n     * @param  {String} arg0 - 内容\n     * @return {Void}\n     */\n    _pro._$setContent = function(_content){\n        this.__editor._$setContent(_content);\n    };\n    /**\n     * 注册命令实现\n     * @method module:ui/editor/editor._$$Editor#_$registCommand\n     * @param  {Array|nej.ut._$$EditorCommand} arg0 - 命令实现类构造\n     * @return {Void}\n     */\n    _pro._$registCommand = function(_class){\n        this.__editor._$registCommand(_class);\n    };\n    /**\n     * 显示编辑器\n     * @method module:ui/editor/editor._$$Editor#_$show\n     * @return {Void}\n     */\n    _pro._$show = function(){\n        this.__body.style.display = '';\n    };\n    /**\n     * 隐藏编辑器\n     * @method module:ui/editor/editor._$$Editor#_$hide\n     * @return {Void}\n     */\n    _pro._$hide = function(){\n        this.__body.style.display = 'none';\n    };\n    /*\n     * 获取图标样式代码\n     * @return {String} 图标样式\n     */\n    var __doGenIconStyle = function(){\n        var _arr=[],_row=20,_col=3;\n        for(var i=0;i<_row;i++)\n            for(var j=0;j<_col;j++)\n                _arr.push('.#<uispace> .z-i-'+i+j+'{background-position:-'+(16*j)+'px -'+(40+i*16)+'px;}');\n        return _arr.join('');\n    };\n    // ui css text\n    _seed_css = _e._$pushCSSText(_css + __doGenIconStyle(),{root:_c._$get('root')});\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/editor/test/custom.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>custom测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n  \t\t<style type=\"text/css\">\n  \t\t\t#editor-parent .mycustom{width:600px;}\n  \t\t</style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">nej custom.js test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<div id='editor-parent'></div>\n\t\t<div id='getcnt'>getcnt</div>\n        <button id='insert'>插入图片</button>\n        <button id='insertIframe'>插入iframe</button>\n\t\t<input id=\"files-upload\" type=\"file\" multiple accept=\"image/gif,image/png\" name=\"file\">\n\t\t<script>\n\t\t\twindow.NEJ_CONF = {\n\t\t\t    root : '/res/'\n\t\t\t}\n\t\t </script>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./custom.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/ui/editor/test/custom.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"custom\",{\n        setup:function(){\n            this._e = nej.e;\n            this._ui = nej.ui;\n            this._v = nej.v;\n        }\n    });\n    //开始单元测试\n    test('生成一个富文本编辑器',function(){\n        expect(0);\n        var _getcnt = this._e._$get('getcnt');\n        var _parent = this._e._$get('editor-parent');\n        var _insert = this._e._$get('insert');\n        var _istiframe = this._e._$get('insertIframe');\n        window._custom = this._ui._$$CustomEditor._$allocate({\n            parent:_parent,\n            clazz:'mycustom'\n        });\n        this._v._$addEvent(_getcnt,'click',function(){\n            alert(_custom.__editor.__copt.area._$getContent({noId:true}));\n        }._$bind(this));\n        this._v._$addEvent(_insert,'click',function(){\n            window._custom.__editor.__copt.area._$getSelectNode();\n            return;\n            window._custom.__editor.__copt.area._$execCommand('inserthtml','<img style=\"max-width:520px;\" src=\"https://www.baidu.com/img/baidu_jgylogo3.gif?v=33154426.gif\" id=+' + new Date() +'+ />')\n        }._$bind(this));\n        this._v._$addEvent(_istiframe,'click',function(){\n            window._custom.__editor.__copt.area._$execCommand('inserthtml','<iframe width=\"400\" height=\"300\" class=\"videoPlayer\" src=\"/res/videoplayer/assets/index.html?src=http%3A%2F%2Fnos-yx.netease.com%2Fyixinpublic%2Fpr_7puzwahrjwnicckqack1tg%3D%3D_1433388652_8618_translated.mp4&amp;type=mp4&amp;full=false\" frameborder=\"0\"></iframe>')\n        }._$bind(this));\n    });\n}\nmodule('依赖模块');\n\ntest('define',function(){expect(0);\n    define('{pro}custom.test.js',[\n        '../custom.js',\n        'base/element'\n        ],f);\n});\n// test('define',function(){expect(0);\n//     define('{pro}src/ui/customTest.js',[\n//         'base/platform',\n//         '../mywidget/{platform}hack.js',\n//         '../../..////../src/ui/editor/custom.js',\n//         'base/element',\n//         '{pro}log.js'\n//         ],f);\n// });\n"
  },
  {
    "path": "src/ui/item/item.js",
    "content": "/*\n * ------------------------------------------\n * 列表项控件基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/item/item */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'ui/base'\n],function(NEJ,_k,_i,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 列表项控件基类\n     *\n     * 页面结构举例\n     *\n     * ```html\n     * <div id='item-box'></div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/klass',\n     *     'ui/item/item'\n     * ],function(_k,_i0,_p,_o,_f,_r){\n     *     var _  = NEJ.P,\n     *         _p = _('nej.ut'),\n     *         _e = _('nej.e');\n     *     // 第一步：新建一个类，继承自此基类\n     *     var _html_key = _e._$addNodeTemplate('<div>123</div>');\n     *\n     *     _p._$$MyItem = _k._$klass();\n     *     _proMyItem = _p._$$MyItem._$extend(_i0._$$Item);\n     *     _proMyItem.__reset = function(_options){\n     *         this.__data = _options.data;\n     *         this.__super(_options);\n     *     }\n     *\n     *     _proMyItem.__doRefresh = function(){\n     *         // 刷新一项，设置数据{name:'sean'}\n     *         this.__body.innerText = this.__data.name;\n     *     };\n     *\n     *     _proMyItem.__initXGui = function(){\n     *         this.__seed_html = _html_key;\n     *     };\n     * });\n     * // 第二步：生成item列表\n     * // 可以自己循环list，生成item\n     * NEJ.define([\n     *     'base/event',\n     *     'path/to/custom/myitem.js'\n     * ],function(_e,_i0,_p,_o,_f,_r){\n     *     var _item = _i0._$$MyItem._$allocate({\n     *         parent:'item-box',\n     *         data:list[i]\n     *     });\n     *     // 可以利用_e._$getItemTemplate接口，返回item列表\n     *     _e._$getItemTemplate(\n     *         [{name:'jack'},{name:'sean'}],\n     *         _i0._$$MyItem,\n     *         {parent:'item-box'}\n     *     );\n     * });\n     * ```\n     *\n     * @class     module:ui/item/item._$$Item\n     * @extends   module:ui/base._$$Abstract\n     * @param     {Object} arg0  - 可选配置参数\n     * @property  {Object} data  - 当前项绑定的数据\n     * @property  {Number} index - 当前项的索引\n     * @property  {Number} total - 总列表长度\n     * @property  {Array}  range - 当前项所在的列表片段方位(begin,end)\n     */\n    _p._$$Item = _k._$klass();\n    _pro = _p._$$Item._$extend(_i._$$Abstract);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:ui/item/item._$$Item#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__id = this.__genId();\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/item/item._$$Item#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__index = _options.index;\n        this.__total = _options.total;\n        this.__range = _options.range;\n        this._$refresh(_options.data);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/item/item._$$Item#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__data;\n        delete this.__index;\n        delete this.__total;\n        delete this.__range;\n    };\n    /**\n     * 刷新项,子类实现具体逻辑\n     *\n     * @abstract\n     * @method module:ui/item/item._$$Item#__doRefresh\n     * @return {Void}\n     */\n    _pro.__doRefresh = _f;\n    /**\n     * 生成ID\n     *\n     * @protected\n     * @method module:ui/item/item._$$Item#__genId\n     * @return {String} ID\n     */\n    _pro.__genId = (function(){\n        var _seed = +new Date;\n        return function(){\n            return 'itm-'+(++_seed);\n        };\n    })();\n    /**\n     * 取项标识\n     *\n     * 脚本举例\n     * ```javascript\n     * // 获取当前item的id标识\n     * _item._$getId();\n     * ```\n     *\n     * @method module:ui/item/item._$$Item#_$getId\n     * @return {String} 项标识\n     */\n    _pro._$getId = function(){\n        return this.__id;\n    };\n    /**\n     * 取项绑定数据\n     *\n     * 脚本举例：\n     * ```javascript\n     * // 获取当前item的数据信息\n     * _item._$getData();\n     * ```\n     *\n     * @method module:ui/item/item._$$Item#_$getData\n     * @return {Object} 数据信息\n     */\n    _pro._$getData = function(){\n        return this.__data;\n    };\n    /**\n     * 刷新项绑定的数据\n     *\n     * 脚本举例：\n     * ```javascript\n     * // 获取当前item的数据信息\n     * _item._$refresh({\n     *     a:'aaaaa',\n     *     b:'bbbbb'\n     * });\n     * ```\n     *\n     * @method module:ui/item/item._$$Item#_$refresh\n     * @param  {Object} arg0 - 项绑定的数据\n     * @return {Void}\n     */\n    _pro._$refresh = function(_data){\n        this.__data  = _data||{};\n        this.__doRefresh(this.__data);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/ui/item/list.js",
    "content": "/*\n * ------------------------------------------\n * 列表项基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/item/list */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'ui/item/item'\n],function(NEJ,_k,_i0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 列表项基类对象\n     *\n     * @class     module:ui/item/list._$$ListItem\n     * @extends   module:ui/item/item._$$Item\n     * @param     {Object} arg0 - 配置参数\n     * @property  {String} pkey - 主键字段名称，默认为id\n     */\n    /**\n     * 删除列表项触发事件\n     *\n     * @event    module:ui/item/list._$$ListItem#ondelete\n     * @param    {Object} arg0 - 事件信息\n     * @property {String} id   - 项标识\n     * @property {Object} data - 项绑定的数据\n     *\n     */\n    _p._$$ListItem = _k._$klass();\n    _pro = _p._$$ListItem._$extend(_i0._$$Item);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/item/list._$$ListItem#__reset\n     * @param  {Object} arg0 - 配置信息\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__pkey = _options.pkey||'id';\n        this.__prefix = _options.prefix||'';\n        this.__super(_options);\n    };\n    /**\n     * 删除列表项触发事件\n     *\n     * @protected\n     * @method module:ui/item/list._$$ListItem#__onDelete\n     * @return {Void}\n     */\n    _pro.__onDelete = function(_data){\n        this._$dispatchEvent('ondelete',{\n            ext:_data,\n            id:this._$getId(),\n            data:this._$getData(),\n            body:this._$getBody()\n        });\n    };\n    /**\n     * 删除列表项触发事件\n     *\n     * @protected\n     * @method module:ui/item/list._$$ListItem#__onUpdate\n     * @return {Void}\n     */\n    _pro.__onUpdate = function(_data){\n        this._$dispatchEvent('onupdate',{\n            ext:_data,\n            id:this._$getId(),\n            data:this._$getData(),\n            body:this._$getBody()\n        });\n    };\n    /**\n     * 刷新项绑定的数据<br/>\n     *\n     * 脚本举例：\n     * ```javascript\n     * // 获取当前item的数据信息\n     * _item._$refresh({\n     *     a:'aaaaa',\n     *     b:'bbbbb'\n     * });\n     * ```\n     *\n     * @method module:ui/item/list._$$ListItem#_$refresh\n     * @param  {Object} arg0 - 项绑定的数据\n     * @return {Void}\n     */\n    _pro._$refresh = function(_data){\n        this.__super(_data);\n        var _id = this.__data[this.__pkey];\n        this.__id = (this.__prefix+_id)||this.__genId();\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/layer/card.css",
    "content": ".#<uispace>{position:absolute;background:#fff;}"
  },
  {
    "path": "src/ui/layer/card.js",
    "content": "/*\n * ------------------------------------------\n * 卡片控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/layer/card */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'ui/layer/layer',\n    'text!./card.css'\n],function(NEJ,_k,_e,_v,_i0,_css,_p,_o,_f,_r){\n    var _pro,\n        _seed_css = _e._$pushCSSText(_css);\n    /**\n     * 卡片控件\n     *\n     * 页面结构举例\n     * ```html\n     * <div id=\"card-box\" class=\"box\"></div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/event',\n     *     'ui/layer/card'\n     * ],function(_e,_i0,_p,_o,_f,_r){\n     *     // 生成卡片的实例\n     *     var _card = _i0._$$Card._$allocate({\n     *         parent:'card-box',\n     *         top:10,\n     *         left:10,\n     *         destroyable:true,\n     *         content:'<div>您要显示的内容HTML或节点</div>',\n     *         oncontentready:function(_html){\n     *             // 卡片里塞入内容的回调\n     *         },\n     *         onbeforerecycle:function(){\n     *             // 回收前触发的回调\n     *         }\n     *     });\n     *     // 默认就是显示的，此方法对应_$hide();\n     *     _card._$show();\n     * });\n     * ```\n     *\n     * @class     module:ui/layer/card._$$Card 卡片控件\n     * @extends   module:ui/layer/layer._$$Layer\n     * @param     {Object}  arg0   - 可选配置参数\n     * @property  {String}  top    - 卡片垂直位置\n     * @property  {String}  left   - 卡片水平位置\n     * @property  {Boolean} nostop - 是否禁用事件阻止\n     */\n    _p._$$Card = _k._$klass();\n    _pro = _p._$$Card._$extend(_i0._$$Layer);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/layer/card._$$Card#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__doInitDomEvent([[\n            document,'click',\n            this.__onDocClick._$bind(this)\n        ]]);\n        this.__nostop = !!_options.nostop;\n        this.__position = {\n            top:_options.top,\n            left:_options.left\n        };\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/layer/card._$$Card#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        delete this.__pbox;\n        delete this.__fbox;\n        delete this.__align;\n        delete this.__fitable;\n        delete this.__byPoint;\n        delete this.__position;\n        this.__super();\n    };\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/layer/card._$$Card#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css = _seed_css;\n    };\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method module:ui/layer/card._$$Card#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        this.__ncnt = this.__body;\n        _v._$addEvent(\n            this.__body,'click',\n            this.__doCheckStop._$bind(this)\n        );\n    };\n    /**\n     * 文档点击事件\n     *\n     * @protected\n     * @method module:ui/layer/card._$$Card#__onDocClick\n     * @return {Void}\n     */\n    _pro.__onDocClick = function(_event){\n        // fix firefox fire click when right button click\n        if (_event.button!=2) this._$hide();\n    };\n    /**\n     * 检查点击节点默认事件\n     *\n     * @protected\n     * @method module:ui/layer/card._$$Card#__doCheckStop\n     * @return {Void}\n     */\n    _pro.__doCheckStop = function(_event){\n        if (this.__nostop) return;\n        _v._$stopBubble(_event);\n        var _element = _v._$getElement(_event);\n        if (_element.tagName=='A')\n            _v._$stopDefault(_event);\n    };\n    /**\n     * 设置对齐方式\n     *\n     * @protected\n     * @method module:ui/layer/card._$$Card#__setAlign\n     * @param  {String} arg0 - 对齐方式\n     * @return {Void}\n     */\n    _pro.__setAlign = (function(){\n        var _reg = /\\s+/i;\n        return function(_align){\n            _align = (_align||'').trim()\n                     .toLowerCase().split(_reg);\n            _align[0] = _align[0]||'bottom';\n            _align[1] = _align[1]||'left';\n            this.__align = _align;\n        };\n    })();\n    /**\n     * 根据适应方式取位置信息\n     *\n     * @protected\n     * @method module:ui/layer/card._$$Card#__doCalPosition\n     * @param  {String} arg0 - 适应位置\n     * @return {Object} 位置信息\n     */\n    _pro.__doCalPosition = function(_align){\n        var _result = {},\n            _fbox = this.__fbox,\n            _pbox = _e._$getPageBox(),\n            _width = this.__body.offsetWidth,\n            _height = this.__body.offsetHeight;\n        switch(_align[0]){\n            case 'top':\n                _result.top  = _fbox.top-_height;\n                _result.left = _align[1]=='right'\n                             ? _fbox.left+_fbox.width-_width\n                             : _fbox.left;\n            break;\n            case 'left':\n                _result.left = _fbox.left-_width;\n                _result.top  = _align[1]=='bottom'\n                             ? _fbox.top+_fbox.height-_height\n                             : _fbox.top;\n            break;\n            case 'right':\n                _result.left = _fbox.left+_fbox.width;\n                _result.top  = _align[1]=='bottom'\n                             ? _fbox.top+_fbox.height-_height\n                             : _fbox.top;\n            break;\n            default:\n                _result.top  = _fbox.top+_fbox.height;\n                _result.left = _align[1]=='right'\n                             ? _fbox.left+_fbox.width-_width\n                             : _fbox.left;\n            break;\n        }\n        return _result;\n    };\n    /**\n     * 调整显示位置\n     *\n     * @protected\n     * @method module:ui/layer/card._$$Card#__doPositionAlign\n     * @return {Void}\n     */\n    _pro.__doPositionAlign = function(){\n        if (!this.__fitable){\n            this._$setPosition(this.__position);\n            return;\n        }\n        if(!!this.__byPoint){\n            this._$setPosition(this.__pbox);\n            return;\n        }\n        if (!!this.__fbox)\n            this._$setPosition(\n                this.__doCalPosition(this.__align)\n            );\n    };\n\n    /**\n     * 根据卡片规则计算左上角的坐标\n     *\n     * @protected\n     * @method module:ui/layer/card._$$Card#__doFindPosition\n     * @return {Object} 卡片左上角坐标{top:20,left:10}\n     */\n    _pro.__doFindPosition = function(_element,_delta,_event){\n        _delta = _delta||_o;\n        var _pageBox = _e._$getPageBox(),\n            _x = _v._$pageX(_event) + (_delta.left||0),\n            _y = _v._$pageY(_event) + (_delta.top||0),\n            _width = _element.offsetWidth + (_delta.right||0),\n            _height= _element.offsetHeight + (_delta.bottom||0),\n            _pageWidth = _pageBox.scrollWidth,\n            _pageHeight= _pageBox.scrollHeight,\n            _temp0 = _x + _width,\n            _temp1 = _y + _height;\n        switch(this.__align[0]){\n            case 'top':\n                _y = (_temp1 > _pageHeight) ? (_y - _height): _y;\n                if(this.__align[1] == 'right'){\n                    _x = (_x - _width) < 0 ? 0 : (_x - _width);\n                }else{\n                    _x = (_temp0 > _pageWidth) ? (_pageWidth - _width): _x;\n                }\n            break;\n            case 'left':\n                _x = (_temp0 > _pageWidth) ? (_pageWidth - _width): _x;\n                if(this.__align[1] == 'top'){\n                    _y = (_temp1 > _pageHeight) ? (_y - _height): _y;\n                }else{\n                    _y = (_y - _height) < 0 ? _y : (_y - _height);\n                }\n            break;\n            case 'right':\n                _x = (_x - _width) < 0 ? 0 : (_x - _width);\n                if(this.__align[1] == 'top'){\n                    _y =(_temp1 > _pageHeight) ? (_y - _height) : _y;\n                }else{\n                    _y = (_y - _height) < 0 ? _y : (_y - _height);\n                }\n            break;\n            default:\n                _y = (_y - _height) < 0 ? _y : (_y - _height);\n                if(this.__align[1] == 'left'){\n                    _x = (_temp0 > _pageWidth) ? (_pageWidth - _width): _x;\n                }else{\n                    _x = (_x - _width) < 0 ? 0 : (_x - _width);\n                }\n            break;\n        }\n        return {top:_y,left:_x};\n    };\n    /**\n     * 偏移量信息对象\n     *\n     * @typedef  {Object} module:ui/layer/card._$$Card~Delta\n     * @property {Number} top    - 上偏移量\n     * @property {Number} right  - 右偏移量\n     * @property {Number} bottom - 下偏移量\n     * @property {Number} left   - 左偏移量\n     */\n    /**\n     * 对齐方式信息对象\n     *\n     * @typedef  {Object} module:ui/layer/card._$$Card~Align\n     * @property {Number} top    - 上对齐\n     * @property {Number} right  - 右对齐\n     * @property {Number} bottom - 下对齐\n     * @property {Number} left   - 左对齐\n     */\n    /**\n     * 通过参照节点显示卡片位置\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/event',\n     *     'ui/layer/card'\n     * ],function(_e,_i0,_p,_o,_f,_r){\n     *     // 生成卡片的实例\n     *     var _card = _i0._$$Card._$allocate({\n     *         parent:'card-box',\n     *         top:10,\n     *         left:10,\n     *         destroyable:true,\n     *         content:'<div>您要显示的内容HTML或节点</div>',\n     *         oncontentready:function(_html){\n     *             // 卡片里塞入内容的回调\n     *         },\n     *         onbeforerecycle:function(){\n     *             // 回收前触发的回调\n     *         }\n     *     });\n     *     // 卡片显示的时候，根据target节点来定位,卡片位置固定\n     *     // align代表卡片的对齐方式\n     *     // delta代表偏移量\n     *     _card._$showByReference({\n     *         align:'top right',\n     *         target:document.body,\n     *         delta:{top:10,right:20}\n     *     });\n     *     // 另外一种情况，根据鼠标点击来定位卡片位置\n     *     // 需要传入鼠标事件的event信息\n     *     // 鼠标传入的点的坐标为基准\n     *     // align表示，此点代表卡片的哪个位置\n     *     // delta代表偏移量\n     *     // 如果卡片超出可视区域范围，会参照windows桌面右键卡片布局\n     *     _card._$showByReference({\n     *         event:_event,\n     *         align:'top right',\n     *         target:document.body,\n     *         delta:{top:10,right:20}\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:ui/layer/card._$$Card#_$showByReference\n     * @param    {Object} arg0  - 可选配置参数\n     * @property {module:ui/layer/card._$$Card~Delta} delta - 位置偏移\n     * @property {module:ui/layer/card._$$Card~Align} align - 卡片对齐位置，默认为'top left'\n     * |   整体位置           |   对齐方式              |\n     * | :---                 | :---                    |\n     * | top/right/bottom/left| top/bottom/left/right   |\n     * @property {Boolean} fitable - 是否需要调整卡片位置使其适应页面\n     * @return   {Void}\n     */\n    _pro._$showByReference = (function(){\n        var _doCalTargetBox = function(_element,_delta){\n            _element = _e._$get(_element);\n            if (!_element) return;\n            _delta = _delta||_o;\n            var _offset = _e._$offset(_element);\n            return {top:_offset.y-(_delta.top||0),\n                    left:_offset.x-(_delta.left||0),\n                    width:_element.offsetWidth+(_delta.right||0),\n                    height:_element.offsetHeight+(_delta.bottom||0)};\n        };\n        return function(_options){\n            _options = _options||_o;\n            this.__byPoint = _options.event;\n            this.__setAlign(_options.align);\n            if(!!this.__byPoint)\n                this.__pbox = this.__doFindPosition(_options.target,_options.delta,this.__byPoint);\n            this.__fbox = _doCalTargetBox(\n                          _options.target,_options.delta);\n            this.__fitable = !!_options.fitable;\n            this._$show();\n        };\n    })();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/layer/card.wrapper.js",
    "content": "// link to ui/layer/wrapper/card for compatible\n// use ui/layer/wrapper/card for new project\nNEJ.define(['./wrapper/card.js'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/layer/demo/card.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test window</title>\n    <meta charset=\"utf-8\" />\n    <style>\n        body,html{width:100%;height:100%;}\n        #abc{border:1px solid #9FAC87;width:100px;height:30px;line-height:30px;}\n        form{padding:20px;background:#0C32F6}\n    </style>\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n  </head>\n  <body>\n    <div id=\"abc\">xxxxxxxxxxxx</div>\n    <textarea name=\"ntp\" id=\"tpl-win\">\n      <form>\n         <input type=\"text\" name=\"time\" data-type=\"date\" data-required=\"true\" data-message=\"必须设置日期\"/>\n         <input type=\"button\" name=\"btn\" value=\"ok\"/>\n      </form>\n    </textarea>\n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            'base/klass',\n            'base/event',\n            'base/element',\n            'util/template/tpl',\n            'util/form/form',\n            '../wrapper/card.js'\n        ],function(_k,_v,_x,_e,_t,_i,_p,_o,_f,_r,_pro){\n            \n            _e._$parseTemplate('tpl-win');\n            \n            _p._$$Card = _k._$klass();\n            _pro = _p._$$Card._$extend(_i._$$CardWrapper);\n            \n            _pro.__initXGui = function(){\n                this.__seed_html = 'tpl-win';\n            };\n            \n            _pro.__initNode = function(){\n                this.__super();\n\n            };\n//            var card = _p._$$Card._$allocate({\n//                parent:document.body\n//            });\n//            _v._$addEvent(\n//                    document.body,'click',function(ev){\n//                        _v._$stop(ev);\n//                        card._$showByReference({\n//                            event:ev,\n//                            fitable:!0,\n//                            align:'bottom right',\n//                            target:_x._$get('abc')\n//                        });\n//                    }\n//            );\n\n\n            // init\n            _p._$$Card._$attach('abc',{\n                parent:document.body,\n                align:'right bottom',\n                fixed:!0,\n                onbeforeclick:function(opt){\n                    var pos = _e._$align(\n                            _e._$getPageBox(),\n                            {width:222,height:60},\n                            'right bottom'\n                    );\n                    opt.top = pos.top;\n                    opt.left = pos.left;\n                }\n            });\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/ui/layer/demo/window.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test window</title>\n    <meta charset=\"utf-8\" />\n    <style>\n        body,html{width:100%;height:100%;}\n    </style>\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n  </head>\n  <body>\n      <select><option>1</option><option>2</option></select>\n    <textarea name=\"ntp\" id=\"tpl-win\">\n      <form>\n         <input type=\"text\" name=\"time\" data-type=\"date\" data-required=\"true\" data-message=\"必须设置日期\"/>\n         <input type=\"button\" name=\"btn\" value=\"ok\"/>\n      </form>\n    </textarea>\n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            'base/klass',\n            'base/event',\n            'util/template/tpl',\n            'util/form/form',\n            '../wrapper/window.js'\n        ],function(_k,_v,_e,_t,_i,_p,_o,_f,_r,_pro){\n            \n            _e._$parseTemplate('tpl-win');\n            \n            _p._$$Window = _k._$klass();\n            _pro = _p._$$Window._$extend(_i._$$WindowWrapper);\n            \n            _pro.__initXGui = function(){\n                this.__seed_html = 'tpl-win';\n            };\n            \n            _pro.__initNode = function(){\n                this.__super();\n                _v._$addEvent(\n                    this.__body.btn,'click',\n                    this.__onSubmit._$bind(this)\n                );\n                this.__form = _t._$$WebForm._$allocate({\n                    form:this.__body\n                });\n            };\n            \n            _pro.__onSubmit = function(){\n                if (this.__form._$checkValidity()){\n                    this._$hide();\n                    log('submit form to server');\n                }\n            };\n\n            _pro._$hide = function(){\n                this._super();\n                console.log('11111');\n            };\n\n\n            // init\n            _p._$$Window._$allocate({\n                parent:document.body,\n                draggable:true,\n                align:'left top',\n                mask:true\n            })._$show();\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/ui/layer/layer.js",
    "content": "/*\n * ------------------------------------------\n * 弹出层控件基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/layer/layer */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/util',\n    'ui/base'\n],function(NEJ,_k,_e,_u,_i,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 弹出层控件基类\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/klass',\n     *     'base/element',\n     *     'ui/layer/layer'\n     * ],function(_k,_e,_i0,_p,_o,_f,_r){\n     *     // 第一步：继承此基类生成新类\n     *     var _seed_css = _e._$pushCSSText('.#<uispace>{position:absolute;background:#fff;}');\n     *     _p._$$MyLayer = _k._$klass();\n     *     _proMyLayer = _p._$$MyLayer._$extend(_i0._$$Layer);\n     *\n     *     _proMyLayer.__initXGui = function(){\n     *        this.__seed_css = _seed_css;\n     *     };\n     *\n     *     _proMyLayer.__initNode = function(){\n     *         this.__super();\n     *         // this.__ncnt作为放置卡片内容的容器\n     *         this.__ncnt = this.__body;\n     *     };\n     *\n     *\n     *     // 最后项目中实例化wrapper的实例\n     *      var _ly = _p._$$MyLayerCard._$allocate({\n     *         parent:document.body,\n     *         // 隐藏浮层时，是否销毁\n     *         destroyable:false,\n     *         oncontentready:function(_html){\n     *           // 设置浮层内容的回调\n     *         }\n     *     });\n     * });\n     * // 第二步:实例化一个弹出层\n     * // 一般在layerwrapper控件中使用\n     * // 因为lopt的有默认配置在layerwrapper中\n     * NEJ.define([\n     *     'base/klass',\n     *     'ui/layer/wrapper/layer',\n     *     '/path/custom/to/mylayer.js'\n     * ],function(_k,_i0,_i1,_p,_o,_f,_r){\n     *     // 下面是对layerwrapper的描述\n     *\n     *     // 首先：继承layerwrapper基类生成的一个新类\n     *     _p._$$MyCardWrapper = _k._$klass();\n     *     _proMyCardWrapper = _p._$$MyCardWrapper._$extend\n     *     (_i0._$$LayerWrapper);\n     *\n     *     // 这里返回内容层的实例\n     *     _proMyCardWrapper.__getLayerInstance = function(){\n     *         return _i1._$$MyLayer._$allocate(this.__lopt);\n     *     };\n     *\n     *     // 这里配置lopt参数，生成内容层用\n     *     _proMyCardWrapper.__doInitLayerOptions = function(){\n     *         this.__super();\n     *         this.__lopt.top = null;\n     *         this.__lopt.left = null;\n     *     };\n     * });\n     * ```\n     *\n     * @class     module:ui/layer/layer._$$Layer\n     * @extends   module:ui/base._$$Abstract\n     * @param     {Object}      arg0        - 可选配置参数\n     * @property  {String|Node} content     - 内容HTML代码或者节点对象\n     * @property  {Boolean}     destroyable -调用隐藏时是否自动回收，默认不自动回收\n     * @property  {Boolean}     nohack      - 针对IE6不做hack处理\n     */\n    /**\n     * 显示内容准备就绪触发事件\n     *\n     * @event  module:ui/layer/layer._$$Layer#oncontentready\n     * @param  {Node} arg0 - 显示内容的节点\n     */\n    /**\n     * 控件回收前触发事件\n     *\n     * @event  module:ui/layer/layer._$$Layer#onbeforerecycle\n     */\n    _p._$$Layer = _k._$klass();\n    _pro = _p._$$Layer._$extend(_i._$$Abstract);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/layer/layer._$$Layer#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this._$setEvent('oncontentready',\n                        _options.oncontentready||\n                        this.__doInitContent._$bind(this));\n        this.__nohack = !!_options.nohack;\n        this.__destroyable = !!_options.destroyable;\n        this._$setContent(_options.content);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/layer/layer._$$Layer#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this._$dispatchEvent('onbeforerecycle');\n        this.__super();\n        this.__doHide();\n        this._$setContent('');\n        _e._$style(this.__body,{top:'',left:''});\n    };\n    /**\n     * 初始化内容区域，子类实现具体逻辑\n     *\n     * @abstract\n     * @method module:ui/layer/layer._$$Layer#__doInitContent\n     * @param  {Node} arg0 - 内容区容器节点\n     * @return {Void}\n     */\n    _pro.__doInitContent = _f;\n    /**\n     * 调整显示位置，子类实现具体业务逻辑\n     *\n     * @abstract\n     * @method module:ui/layer/layer._$$Layer#__doPositionAlign\n     * @return {Void}\n     */\n    _pro.__doPositionAlign = _f;\n    /**\n     * 控件隐藏\n     *\n     * @protected\n     * @method module:ui/layer/layer._$$Layer#__doHide\n     * @return {Void}\n     */\n    _pro.__doHide = function(){\n        _e._$removeByEC(this.__body);\n        if (!!this.__mask){\n            _e._$unmask(this.__body);\n            delete this.__mask;\n        }\n    };\n    /**\n     * 设置层显示内容\n     *\n     * 脚本举例\n     * ```javascript\n     * // 设置层里面展示的内容\n     * _ly._$setContent('节点或者字符串');\n     * ```\n     *\n     * @method module:ui/layer/layer._$$Layer#_$setContent\n     * @param  {String|Node} arg0 - 内容HTML代码或者节点\n     * @return {Void}\n     */\n    _pro._$setContent = function(_content){\n        if (!this.__body||\n            !this.__ncnt||\n            _content==null) return;\n        _content = _content||'';\n        _u._$isString(_content)\n        ? this.__ncnt.innerHTML = _content\n        : this.__ncnt.appendChild(_content);\n        this._$dispatchEvent('oncontentready',this.__ncnt);\n    };\n    /**\n     * 设置位置\n     *\n     * 脚本举例\n     * ```javascript\n     * // 设置浮层位置\n     * _ly._$setPosition({top:100,left:200});\n     * ```\n     *\n     * @method module:ui/layer/layer._$$Layer#_$setPosition\n     * @param  {Object} arg0 - 位置信息，如{top:100,left:200}\n     * @return {Void}\n     */\n    _pro._$setPosition = function(_offset){\n        var _value = _offset.top;\n        if (_value!=null){\n            _value += 'px';\n            _e._$setStyle(this.__body,'top',_value);\n            _e._$setStyle(this.__mask,'top',_value);\n        }\n        var _value = _offset.left;\n        if (_value!=null){\n            _value += 'px';\n            _e._$setStyle(this.__body,'left',_value);\n            _e._$setStyle(this.__mask,'left',_value);\n        }\n    };\n    /**\n     * 显示控件\n     *\n     * 脚本举例\n     * ```javascript\n     * // 显示浮层\n     * _ly._$show();\n     * ```\n     *\n     * @method module:ui/layer/layer._$$Layer#_$show\n     * @return {Void}\n     */\n    _pro._$show = function(){\n        _e._$setStyle(this.__body,'visibility','hidden');\n        this.__super();\n        this.__doPositionAlign();\n        _e._$setStyle(this.__body,'visibility','');\n        if (!this.__nohack){\n            this.__mask = _e._$mask(this.__body);\n        }\n    };\n    /**\n     * 隐藏控件\n     *\n     * 脚本举例\n     * ```javascript\n     * // 隐藏浮层\n     * _ly._$hide();\n     * ```\n     *\n     * @method module:ui/layer/layer._$$Layer#_$hide\n     * @return {Void}\n     */\n    _pro._$hide = function(){\n        this.__destroyable ? this._$recycle()\n                           : this.__doHide();\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/layer/layer.wrapper.js",
    "content": "﻿// link to ui/layer/wrapper/layer for compatible\n// use ui/layer/wrapper/layer for new project\nNEJ.define(['./wrapper/layer.js'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/layer/test/card.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>card测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style type=\"text/css\">\n\t\t\t.box{position:relative;}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit card test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<div id=\"card-box\" class=\"box\"></div>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./card.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/ui/layer/test/card.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"ui-card\");\n\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _p = _('nej.ui');\n\n    //开始单元测试\n    test('card',function(){\n        stop();\n        var _card = _p._$$Card._$allocate({\n            parent:'card-box',\n            top:10,\n            left:10,\n            destroyable:true,\n            content:'<div>请点击一下页面，完成卡片的回收</div>',\n            oncontentready:function(_html){\n                ok(true,'设置卡片内容成功');\n            },\n            onbeforerecycle:function(){\n                ok(true,'destroyable属性决定回收前是否触发');\n                start();\n            }\n        });\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}card.test.js',['ui/layer/card'],f);\n});"
  },
  {
    "path": "src/ui/layer/test/layer.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>layer测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit layer test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n \t\t<script src=\"../../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./layer.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/ui/layer/test/layer.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"layer\");\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _p = _('nej.ui');\n        \n    //开始单元测试\n    test('layer',function(){\n\t\tstop();\n        var _ly = _p._$$MyLayerCard._$allocate({\n\t\t\tparent:document.body,\n            destroyable:false,\n            oncontentready:function(_html){\n                ok(true,'设置卡片内容成功');\n\t\t\t\tstart();\n            }\n        });\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}layer.test.js',['{pro}mylayercard.js'],f);\n});"
  },
  {
    "path": "src/ui/layer/test/mylayer.js",
    "content": "/*\n * ------------------------------------------\n * 卡片控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nvar f = function(){\n    var _  = NEJ.P,\n        _o = NEJ.O,\n        _v = _('nej.v'),\n        _e = _('nej.e'),\n        _p = _('nej.ui'),\n        _proMyLayer;\n    if (!!_p._$$MyLayer) return;\n    // ui css text\n    var _seed_css = _e._$pushCSSText('.#<uispace>{position:absolute;background:#fff;}');\n    /**\n     * 卡片控件\n     * @param   {Object} 可选配置参数\n     * @property  {String} top  卡片垂直位置\n     * @property  {String} left 卡片水平位置\n     */\n    _p._$$MyLayer = NEJ.C();\n    _proMyLayer = _p._$$MyLayer._$extend(_p._$$Layer);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method {__reset}\n     * @param  {Object} 可选配置参数\n     * @return {Void}\n     */\n    _proMyLayer.__reset = function(_options){\n        this.__super(_options);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method {__destroy}\n     * @return {Void}\n     */\n    _proMyLayer.__destroy = function(){\n        this.__super();\n    };\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method {__initXGui}\n     * @return {Void}\n     */\n    _proMyLayer.__initXGui = function(){\n        this.__seed_css = _seed_css;\n    };\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method {__initNode}\n     * @return {Void}\n     */\n    _proMyLayer.__initNode = function(){\n        this.__super();\n        this.__ncnt = this.__body;\n    };\n};\ndefine('{pro}mylayer.js',\n      ['ui/layer/layer'],f);\n"
  },
  {
    "path": "src/ui/layer/test/mylayercard.js",
    "content": "var f = function(){\n    var _  = NEJ.P,\n        _f = NEJ.F,\n        _u = _('nej.u'),\n        _e = _('nej.e'),\n        _p = _('nej.ui'),\n        _proMyLayerCard;\n    var _seed_html = _e._$addNodeTemplate('<div>您要展示的内容部分</div>');\n    /**\n     * 弹出层封装基类对象，主要实现层里面内容部分的业务逻辑\n     * @class   弹出层封装基类对象\n     * @extends {nej.ui._$$CardWrapper}\n     * @param   {Object} _options 可选配置参数\n     *\n     */\n    _p._$$MyLayerCard = NEJ.C();\n      _proMyLayerCard = _p._$$MyLayerCard._$extend(_p._$$MyCardWrapper);\n\n    _proMyLayerCard.__initXGui = function(){\n        this.__seed_html = _seed_html;\n    };\n};\ndefine('{pro}mylayercard.js',\n      ['{pro}mylayerwrapper.js'],f);"
  },
  {
    "path": "src/ui/layer/test/mylayerwrapper.js",
    "content": "/*\n * ------------------------------------------\n * 弹出卡片封装基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nvar f = function(){\n    var _  = NEJ.P,\n        _o = NEJ.O,\n        _e = _('nej.e'),\n        _v = _('nej.v'),\n        _u = _('nej.u'),\n        _p = _('nej.ui'),\n        _proMyCardWrapper;\n    if (!!_p._$$MyCardWrapper) return;\n    /**\n     *\n     * @class   module:nej.ui._$$MyCardWrapper 弹出卡片封装基类对象\n     * @extends {nej.ui._$$LayerWrapper}\n     * @param   {Object} 可选配置参数\n     *\n     */\n    _p._$$MyCardWrapper = NEJ.C();\n    _proMyCardWrapper = _p._$$MyCardWrapper._$extend(_p._$$LayerWrapper);\n    /**\n     * 构建弹层控件实例，子类实现具体业务逻辑\n     *\n     * @protected\n     * @method {__getLayerInstance}\n     * @return {nej.ui._$$Layer} 弹层控件实例\n     */\n    _proMyCardWrapper.__getLayerInstance = function(){\n        return _p._$$MyLayer._$allocate(this.__lopt);\n    };\n    /**\n     * 初始化弹层控件可选配置参数\n     *\n     * @protected\n     * @method {__doInitLayerOptions}\n     * @return {Void}\n     */\n    _proMyCardWrapper.__doInitLayerOptions = function(){\n        _p._$$MyCardWrapper._$supro\n          .__doInitLayerOptions.apply(this,arguments);\n        this.__lopt.top = null;\n        this.__lopt.left = null;\n    };\n};\ndefine('{pro}mylayerwrapper.js',\n      ['ui/layer/layer.wrapper'\n      ,'{pro}mylayer.js'],f);"
  },
  {
    "path": "src/ui/layer/test/mywindow.js",
    "content": "var f = function(){\n    var _  = NEJ.P,\n        _f = NEJ.F,\n        _u = _('nej.u'),\n        _e = _('nej.e'),\n        _p = _('nej.ui'),\n        _proMyWindow;\n    var _seed_html = _e._$addNodeTemplate('<div>您要展示的内容部分</div>');\n    /**\n     * 弹出层封装基类对象，主要实现层里面内容部分的业务逻辑\n     * @class   弹出层封装基类对象\n     * @extends {nej.ui._$$CardWrapper}\n     * @param   {Object} _options 可选配置参数\n     *\n     */\n    _p._$$MyWindow = NEJ.C();\n      _proMyWindow = _p._$$MyWindow._$extend(_p._$$WindowWrapper);\n\n    _proMyWindow.__initXGui = function(){\n        this.__seed_html = _seed_html;\n    };\n\n\t_proMyWindow.__reset = function(_options){\n\t\t_options = _options || {};\n        _options.draggable = !!_options.draggable ? true : false;\n        _options.destroyable = !!_options.destroyable ? true : false;\n\t\tthis.__super(_options);\n\t};\n};\ndefine('{pro}mywindow.js',\n      ['ui/layer/window.wrapper'],f);"
  },
  {
    "path": "src/ui/layer/test/window.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>window测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style type=\"text/css\">\n\t\t\tbody, html{width:100%;height:100%;border:0;padding:0;margin:0;}\n\t\t\t.box{position:relative;width:500px;height:200px;}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit window test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<div id=\"window-box\" class=\"box\"></div>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./window.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/ui/layer/test/window.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"ui-window\");\n\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _p = _('nej.ui');\n\n    //开始单元测试\n    test('window',function(){\n        stop();\n        var _window = _p._$$Window._$allocate({\n            parent:document.body,\n            title:'弹出框标题',\n            align:'left middle',\n            draggable:true,\n            onclose:function(){\n                ok(true,'成功关闭窗口');\n                start();\n            }\n        });\n        _window._$show();\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}window.test.js',['ui/layer/window'],f);\n});"
  },
  {
    "path": "src/ui/layer/test/window.wrapper.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>windowWarpper测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style type=\"text/css\">\n\t\t\t.box{position:relative;}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit windowWarpper test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n \t\t<script src=\"../../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./window.wrapper.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/ui/layer/test/window.wrapper.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"ui-windowWarpper\");\n    \n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _p = _('nej.ui'),\n        _v = _('nej.v');\n        \n    //开始单元测试\n    test('windowWarpper',function(){\n        stop();\n        var _myCard = _p._$$MyWindow._$allocate({\n            parent:document.body,\n            title:'窗口标题',\n            draggable:false,\n            mask:true,\n            onclose:function(){\n                ok(true,'成功关闭浮层');\n                start();\n            }\n        });\n    });\n    \n//    test('windowWarpper-2',function(){\n//        stop();\n//        var _myCard = _p._$$MyWindow._$allocate({\n//            parent:document.body,\n//            title:'窗口标题2',\n//            draggable:true,\n//            mask:true,\n//            onclose:function(){\n//                ok(true,'成功关闭浮层');\n//                start();\n//            }\n//        });\n//    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}window.wrapper.test.js',['{pro}mywindow.js'],f);\n});"
  },
  {
    "path": "src/ui/layer/window.css",
    "content": ".#<uispace>{position:absolute;z-index:1000;border:1px solid #aaa;background:#fff;}\n.#<uispace> .zbar{line-height:30px;background:#8098E7;border-bottom:1px solid #aaa;}\n.#<uispace> .zcnt{padding:10px 5px;}\n.#<uispace> .zttl{margin-right:20px;text-align:left;}\n.#<uispace> .zcls{position:absolute;top:5px;right:0;width:20px;height:20px;line-height:20px;cursor:pointer;}\n"
  },
  {
    "path": "src/ui/layer/window.html",
    "content": "<div>\n  <div class=\"zbar\"><div class=\"zttl\">标题</div></div>\n  <div class=\"zcnt\"></div>\n  <span class=\"zcls\" title=\"关闭窗体\">×</span>\n</div>"
  },
  {
    "path": "src/ui/layer/window.js",
    "content": "/*\n * ------------------------------------------\n * 窗体控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/layer/window */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'base/util',\n    'ui/layer/layer',\n    'ui/mask/mask',\n    'util/dragger/dragger',\n    'util/template/tpl',\n    'text!./window.css',\n    'text!./window.html'\n],function(NEJ,_k,_e,_v,_u,_i0,_i1,_t0,_t1,_css,_html,_p,_o,_f,_r){\n    var _seed_css = _e._$pushCSSText(_css),\n        _seed_html = _t1._$addNodeTemplate(_html),\n        _pro;\n    /**\n     * 窗体控件\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'ui/layer/window'\n     * ],function(_i0,_p,_o,_f,_r){\n     *     var _window = _i0._$$Window._$allocate({\n     *         parent:document.body,\n     *         title:'弹出框标题',\n     *         align:'left middle',\n     *         draggable:true,\n     *         onclose:function(){\n     *           // 窗口关闭前的回调方法\n     *         }\n     *     });\n     *     // 显示窗口，默认实例化后会显示，如果_$hide()后需要手动调用\n     *     _window._$show();\n     * });\n     * ```\n     *\n     * @class     module:ui/layer/window._$$Window 窗体控件\n     * @extends   module:ui/layer/layer._$$Layer\n     * @param     {Object} arg0       - 可选配置参数\n     * @property  {String} title      -  窗口标题\n     * @property  {String} align      -   相对于视窗位置定义，横向+空格+纵向，默认为center middle\n     * |        横向             |             纵向           |\n     * |        :---             |             :---           |\n     * | left/center/right/auto  |    top/middle/bottom/auto  |\n     * @property  {Boolean} draggable - 是否可拖拽\n     * @property  {nej.ui._$$Mask|Boolean|String} mask  -     盖层信息\n     * |        mask参数             |             含义   |\n     * |        :---                 |             :---   |\n     * | 如果是nej.ui._$$Mask的子类  |    则为盖层构造    |\n     * | 如果是布尔值                |    则使用默认盖层  |\n     * | 如果是字符串                |    则为盖层样式    |\n     */\n    /**\n     * 关闭窗体触发事件\n     *\n     * @event  module:ui/layer/window._$$Window#onclose\n     *\n     */\n    _p._$$Window = _k._$klass();\n    _pro = _p._$$Window._$extend(_i0._$$Layer);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:ui/layer/window._$$Window#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__mopt = {};\n        this.__dopt = {onchange:this.__onDragging._$bind(this)};\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/layer/window._$$Window#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__setMask(_options.mask);\n        this._$setAlign(_options.align);\n        this._$setTitle(_options.title);\n        if (!_options.draggable) return;\n        this.__dragger = _t0._$$Dragger.\n                         _$allocate(this.__dopt);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/layer/window._$$Window#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__align;\n        delete this.__mclz;\n        if (!!this.__imask){\n            this.__imask._$recycle();\n            delete this.__imask;\n        }\n        if (!!this.__dragger){\n            this.__dragger._$recycle();\n            delete this.__dragger;\n        }\n    };\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/layer/window._$$Window#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css = _seed_css;\n        this.__seed_html= _seed_html;\n    };\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method module:ui/layer/window._$$Window#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        // 0 - move bar\n        // 1 - content box\n        // 2 - close btn\n        var _list = _e._$getChildren(this.__body);\n        this.__ncnt = _list[1];\n        this.__dopt.mbar = _list[0];\n        this.__dopt.body = this.__body;\n        _v._$addEvent(_list[2],'mousedown',\n                      this.__onClose._$bind(this));\n        _v._$addEvent(this.__dopt.mbar,'mousedown',\n                      this.__onDragStart._$bind(this));\n        this.__nttl = _e._$getChildren(this.__dopt.mbar)[0];\n    };\n    /**\n     * 关闭窗口\n     *\n     * @protected\n     * @method module:ui/layer/window._$$Window#__onClose\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onClose = function(_event){\n        _v._$stop(_event);\n        this._$dispatchEvent('onclose');\n        this._$hide();\n    };\n    /**\n     * 窗口开始拖动过程\n     *\n     * @protected\n     * @method module:ui/layer/window._$$Window#__onDragStart\n     * @param  {Event} arg0 - 事件信息\n     * @return {Void}\n     */\n    _pro.__onDragStart = function(_event){\n        _v._$dispatchEvent(document,'click');\n    };\n    /**\n     * 窗口拖动过程\n     *\n     * @protected\n     * @method module:ui/layer/window._$$Window#__onDragging\n     * @param  {Object} arg0 - 窗口位置信息\n     * @return {Void}\n     */\n    _pro.__onDragging = function(_event){\n        if (!this.__mask) return;\n        _e._$style(this.__mask,{\n            top:_event.top+'px',\n            left:_event.left+'px'\n        });\n    };\n    /**\n     * 窗口位置调整\n     *\n     * @protected\n     * @method module:ui/layer/window._$$Window#__doPositionAlign\n     * @return {Void}\n     */\n    _pro.__doPositionAlign = (function(){\n        var _func = [function(){return 0;},\n                     function(_scroll,_delta,_key){\n                         return Math.max(0,_scroll[_key]+_delta[_key]/2);\n                     },\n                     function(_scroll,_delta,_key){\n                         return _scroll[_key]+_delta[_key];\n                     }],\n            _keys = ['left','top'];\n        return function(){\n            var _value = {},\n                _style = this.__body.style,\n                _view  = _e._$getPageBox(),\n                _scroll= {left:_view.scrollLeft,top:_view.scrollTop},\n                _delta = {left:_view.clientWidth-this.__body.offsetWidth\n                         ,top:_view.clientHeight-this.__body.offsetHeight};\n            _u._$forEach(_keys,\n                function(_key,_index){\n                    var _handler = _func[this.__align[_index]];\n                    if (!_handler) return;\n                    _value[_key] = _handler(_scroll,_delta,_key);\n                },this);\n            this._$setPosition(_value);\n        };\n    })();\n    /**\n     * 显示盖层\n     *\n     * @protected\n     * @method module:ui/layer/window._$$Window#__doShowMask\n     * @return {Void}\n     */\n    _pro.__doShowMask = function(){\n        if (!this.__imask){\n            if (!this.__mclz) return;\n            this.__mopt.parent = this.__parent;\n            this.__imask = this.__mclz\n                ._$allocate(this.__mopt);\n        }\n        this.__imask._$show();\n    };\n    /**\n     * 隐藏窗体\n     *\n     * @protected\n     * @method module:ui/layer/window._$$Window#__doHide\n     * @return {Void}\n     */\n    _pro.__doHide = function(){\n        if (!!this.__imask)\n            this.__imask._$hide();\n        this.__super();\n    };\n    /**\n     * 设置盖层构造\n     *\n     * @protected\n     * @method module:ui/layer/window._$$Window#__setMask\n     * @param  {nej.ui._$$Mask|Boolean} arg0 - 盖层构造\n     * @return {Void}\n     */\n    _pro.__setMask = function(_mask){\n        if (!!_mask){\n            if (_mask instanceof _i1._$$Mask){\n                this.__imask = _mask;\n                return;\n            }\n            if (_u._$isFunction(_mask)){\n                this.__mclz = _mask;\n                return;\n            }\n            this.__mclz = _i1._$$Mask;\n            if (_u._$isString(_mask))\n                this.__mopt.clazz = _mask;\n            return;\n        }\n        this.__mclz = null;\n    };\n    /**\n     * 设置标题\n     *\n     * 脚本举例\n     * ```javascript\n     * _window._$setTitle('设置浮层标题');\n     * ```\n     *\n     * @method module:ui/layer/window._$$Window#_$setTitle\n     * @param  {String} arg0 - 标题\n     * @return {nej.ui._$$Window}\n     */\n    _pro._$setTitle = function(_title,_html){\n        if (!!this.__nttl){\n            var _method = !_html?'innerText':'innerHTML';\n            this.__nttl[_method] = _title||'标题';\n        }\n        return this;\n    };\n    /**\n     * 设置窗体对齐方式\n     *\n     * 脚本举例\n     * ```javascript\n     * // 设置对齐方式，默认是center,middle\n     * _window._$setAlign();\n     * ```\n     *\n     * @method module:ui/layer/window._$$Window#_$setAlign\n     * @param  {String} arg0 - 对齐方式\n     * @return {nej.ui._$$Window}\n     */\n    _pro._$setAlign = (function(){\n        var _reg = /\\s+/,\n            _halign = {left:0,center:1,right:2,auto:3},\n            _valign = {top:0,middle:1,bottom:2,auto:3};\n        return function(_align){\n            this.__align = (_align||'').split(_reg);\n            var _tmp = _halign[this.__align[0]];\n            if (_tmp==null) _tmp = 1;\n            this.__align[0] = _tmp;\n            var _tmp = _valign[this.__align[1]];\n            if (_tmp==null) _tmp = 1;\n            this.__align[1] = _tmp;\n            return this;\n        };\n    })();\n    /**\n     * 显示窗体\n     *\n     * 脚本举例\n     * ```javascript\n     * _window._$show();\n     * ```\n     *\n     * @method module:ui/layer/window._$$Window#_$show\n     * @return {nej.ui._$$Window}\n     */\n    _pro._$show = function(){\n        this.__super();\n        this.__doShowMask();\n        return this;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/layer/window.wrapper.js",
    "content": "// link to ui/layer/wrapper/window for compatible\n// use ui/layer/wrapper/window for new project\nNEJ.define(['./wrapper/window.js'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/layer/wrapper/card.js",
    "content": "/*\n * ------------------------------------------\n * 弹出卡片封装基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/layer/wrapper/card */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'base/util',\n    'ui/layer/wrapper/layer',\n    'ui/layer/card'\n],function(NEJ,_k,_e,_v,_u,_i0,_i1,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 弹出卡片封装基类对象，主要实现层里面内容部分的业务逻辑\n     *\n     * 页面结构举例\n     * ```html\n     * <div id='cardWarpper-box'></div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/klass',\n     *     'ui/layer/wrapper/card'\n     * ],function(_k,_i0,_p,_o,_f,_r){\n     *     // 第一步：继承此基类生成一个新类\n     *     _p._$$MyCard = _k._$klass();\n     *     _proMyCard = _p._$$MyCard._$extend(_i0._$$CardWrapper);\n     *     // 生成card的内容\n     *     _proMyCard.__initXGui = function(){\n     *         this.__seed_html = _seed_html;\n     *     };\n     * });\n     * // 第二步：实例化一个card对象\n     * NEJ.define([\n     *     '/path/custom/to/mycard.js'\n     * ],function(_i0,_p,_o,_f,_r){\n     *     var _myCard = _i0._$$MyCard._$allocate({\n     *         parent:'cardWarpper-box'\n     *     });\n     * });\n     * ```\n     *\n     * @class   module:ui/layer/wrapper/card._$$CardWrapper\n     * @extends module:ui/layer/wrapper/layer._$$LayerWrapper\n     * @param   {Object} arg0 - 可选配置参数\n     *\n     */\n    _p._$$CardWrapper = _k._$klass();\n    _pro = _p._$$CardWrapper._$extend(_i0._$$LayerWrapper);\n    /**\n     * 卡片绑定到执行节点上\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/klass',\n     *     'ui/layer/wrapper/card'\n     * ],function(_k,_i0,_p,_o,_f,_r){\n     *     // 第一步：继承此基类生成一个新类\n     *     _p._$$MyCard = _k._$klass();\n     *     _proMyCard = _p._$$MyCard._$extend(_i0._$$CardWrapper);\n     *     // 生成card的内容\n     *     _proMyCard.__initXGui = function(){\n     *         this.__seed_html = _seed_html;\n     *     };\n     * });\n     * NEJ.define([\n     *     '/path/custom/to/mycard.js'\n     * ],function(_i0,_p,_o,_f,_r){\n     *     var _node = 'cardWarpper-box';\n     *     var _options = {\n     *         // 卡片偏移量\n     *         delta: {\n     *             bottm: 10,\n     *             right: 10\n     *         },\n     *         // 卡片对齐方式\n     *         align: 'bottom right',\n     *         // 是否需要调整卡片位置使其适应页面\n     *         fitable: true,\n     *         parent:document.body,\n     *         onbeforeclick:function(_options){\n     *                // 修改构造参数\n     *             _options.date = new Date;\n     *             // 阻止打开卡片，同时隐藏已打开的卡片\n     *             // _options.showed 判断卡片是否已经显示\n     *             _options.stopped = !0;\n     *             // TODO something\n     *         }\n     * };\n     * // 生成卡片实例\n     * _i0._$$MyCard._$attach(_node,_options);\n     * });\n     * ```\n     * @method module:ui/layer/wrapper/card._$$CardWrapper._$attach\n     * @param    {String|Node} arg0 -      执行节点\n     *\n     * @param    {Object}   arg1  - 构建卡片配置参数\n     * @property {String}   event - 触发显示卡片事件名称，默认为click事件\n     * @property {Boolean}  fixed - 是否固定位置，如果已固定位置则卡片显示位置不会自动计算\n     * @property {Object}   delta   四周偏移，默认全为0，{top:0,right:0,bottom:0,left:0}\n     * @property {String}   align   - 卡片位置，默认为'bottom left'\n     * @property {Boolean}  fitable - 是否需要调整卡片位置使其适应页面\n     * @property {Boolean}  noclear - 显示卡片之前是否不做卡片清理\n     * @property {Boolean}  toggled - 是否采用切换形式打开卡片，如果卡片已经显示则\n     * @property {Function} onbeforeclick - 点击之前触发事件，用以调整参数，输入卡片构造配置对象，{noclear:true,toggled:true}\n     * @return {Void}\n     */\n    _p._$$CardWrapper._$attach = (function(){\n        var _doShowCard = function(_event,_id,_class,_copt,_sopt){\n            var _instance,\n                _key = _id+'-i',\n                _cache = _class.__cdpol,\n                _noclear = !!_copt.noclear,\n                _toggled = !!_copt.toggled;\n            // check click\n            if (_u._$isFunction(_copt.onbeforeclick)){\n                var _oldc = _copt.noclear,\n                    _oldt = _copt.toggled;\n                try{_copt.onbeforeclick(_copt);}catch(e){}\n                _noclear = !!_copt.noclear;\n                _toggled = !!_copt.toggled;\n                _copt.toggled = _oldt;\n                _copt.noclear = _oldc;\n            }\n            // toggle card\n            var _inst = _cache[_key];\n            if (_toggled&&!!_inst){\n                _inst._$hide();\n                return;\n            }\n            // show card\n            _v._$stop(_event);\n            if (!_noclear){\n                _v._$dispatchEvent(document,'click');\n                _instance = _class._$allocate(_copt);\n            }else{\n                _instance = _class._$getInstanceWithReset(_copt,!0);\n            }\n            // cache wrapper instance\n            _cache[_key] = _instance;\n            _instance._$setEvent(\n               'onbeforerecycle',\n                function(){\n                    delete _cache[_key];\n                });\n            _instance._$showByReference(_sopt);\n        };\n        return function(_node,_options){\n            _node = _e._$get(_node);\n            if (!_node) return;\n            if (!this.__cdpol)\n                 this.__cdpol = {};\n            var _id = _e._$id(_node);\n            if (!!this.__cdpol[_id]) return;\n            _options = _u._$merge({},_options);\n            var _sopt = _u._$fetch({\n                    align:'',delta:null,fitable:!1\n                },_options);\n            _sopt.target = _id;\n            _options.destroyable = !0;\n            if (!_options.fixed){\n                _sopt.fitable = !0;\n                _options.parent = document.body;\n            }\n            this.__cdpol[_id] = [\n                 _id,_options.event||'click',\n                 _doShowCard._$bind2(null,_id,this,_options,_sopt)\n            ];\n            _v._$addEvent.apply(_v,this.__cdpol[_id]);\n        };\n    })();\n    /**\n     * 取消节点绑定的卡片\n     *\n     * @method module:ui/layer/wrapper/card._$$CardWrapper._$detach\n     * @param  {String|Node} arg0 - 执行节点\n     * @return {Void}\n     */\n    _p._$$CardWrapper._$detach = function(_node){\n        if (!this.__cdpol) return;\n        var _id = _e._$id(_node),\n            _event = this.__cdpol[_id];\n        if (!_event) return;\n        delete this.__cdpol[_id];\n        _v._$delEvent.apply(_v,_event);\n        var _instance = this.__cdpol[_id+'-i'];\n        if (!!_instance) _instance._$hide();\n    };\n    /**\n     * 构建弹层控件实例，子类实现具体业务逻辑\n     *\n     * @protected\n     * @method module:ui/layer/wrapper/card._$$CardWrapper#__getLayerInstance\n     * @return {module:ui/layer/card._$$Card} 弹层控件实例\n     */\n    _pro.__getLayerInstance = function(){\n        return _i1._$$Card._$allocate(this.__lopt);\n    };\n    /**\n     * 初始化弹层控件可选配置参数\n     *\n     * @protected\n     * @method module:ui/layer/wrapper/card._$$CardWrapper#__doInitLayerOptions\n     * @return {Void}\n     */\n    _pro.__doInitLayerOptions = function(){\n        this.__super();\n        this.__lopt.top = null;\n        this.__lopt.left = null;\n        this.__lopt.nostop = !1;\n    };\n    /**\n     * 通过参照节点显示卡片位置\n     *\n     * @method module:ui/layer/wrapper/card._$$CardWrapper#_$showByReference\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro._$showByReference = function(_options){\n        if (!!this.__layer)\n            this.__layer._$showByReference(_options);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/layer/wrapper/layer.js",
    "content": "/*\n * ------------------------------------------\n * 弹出层封装基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/layer/wrapper/layer */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/util',\n    'ui/base',\n    'ui/layer/layer'\n],function(NEJ,_k,_e,_u,_i,_i0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 弹出层封装基类对象，主要实现层里面内容部分的业务逻辑\n     *\n     * 脚本举例\n     * ```javascript\n     * // 第一步：继承此基类生成新类\n     * NEJ.define([\n     *     'base/element',\n     *     'ui/layer/wrapper/layer'\n     * ],function(_e,_i0,_p,_o,_f,_r){\n     *     var _seed_css = _e._$pushCSSText('.#<uispace>\n     *     {position:absolute;background:#fff;}');\n     *     _p._$$MyLayer = _k._$klass();\n     *     _proMyLayer = _p._$$MyLayer._$extend(_i0._$$Layer);\n     *\n     *     _proMyLayer.__initXGui = function(){\n     *        this.__seed_css = _seed_css;\n     *     };\n     *\n     *     _proMyLayer.__initNode = function(){\n     *         this.__super();\n     *         // this.__ncnt作为放置卡片内容的容器\n     *         this.__ncnt = this.__body;\n     *     };\n     * });\n     * // 下面是对layerwrapper的描述\n     * NEJ.define([\n     *     'base/klass',\n     *     'ui/layer/wrapper/layer',\n     *     '/path/custom/to/layer.js'\n     * ],function(_k,_i0,_i1,_p,_o,_f,_r){\n     *     // 首先：继承layerwrapper基类生成的一个新类\n     *     _p._$$MyCardWrapper = _k._$klass();\n     *     _proMyCardWrapper = _p._$$MyCardWrapper._$extend(_i0.\n     *     _$$LayerWrapper);\n     *\n     *     // 这里返回内容层的实例\n     *     _proMyCardWrapper.__getLayerInstance = function(){\n     *         return _i1._$$MyLayer._$allocate(this.__lopt);\n     *     };\n     *\n     *     // 这里配置lopt参数，生成内容层用\n     *     _proMyCardWrapper.__doInitLayerOptions = function(){\n     *         this.__super();\n     *         this.__lopt.top = null;\n     *         this.__lopt.left = null;\n     *     };\n     *\n     *     // 最后项目中实例化wrapper的实例\n     *      var _ly = _p._$$MyLayerCard._$allocate({\n     *         parent:document.body,\n     *         // 隐藏浮层时，是否销毁\n     *         destroyable:false,\n     *         oncontentready:function(_html){\n     *           // 设置浮层内容的回调\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @class   module:ui/layer/wrapper/layer._$$LayerWrapper\n     * @extends module:ui/base._$$Abstract\n     * @param   {Object} arg0 - 可选配置参数\n     *\n     */\n    _p._$$LayerWrapper = _k._$klass();\n    _pro = _p._$$LayerWrapper._$extend(_i._$$Abstract);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/layer/wrapper/layer._$$LayerWrapper#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__doInitLayerOptions();\n        this.__super(this\n            .__doFilterOptions(_options));\n        this.__lopt.onbeforerecycle =\n            this._$recycle._$bind(this);\n        this.__layer = this.__getLayerInstance();\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/layer/wrapper/layer._$$LayerWrapper#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this._$dispatchEvent('onbeforerecycle');\n        this.__super();\n        delete this.__lopt;\n        _e._$removeByEC(this.__body);\n        var _layer = this.__layer;\n        if (!!_layer){\n            delete this.__layer;\n            _layer._$recycle();\n        }\n    };\n    /**\n     * 构建弹层控件实例，子类实现具体业务逻辑\n     *\n     * @abstract\n     * @method module:ui/layer/wrapper/layer._$$LayerWrapper#__getLayerInstance\n     * @return {nej.ui._$$Layer} 弹层控件实例\n     */\n    _pro.__getLayerInstance = _f;\n    /**\n     * 将配置参数拆分为两部分，一部分用于弹层控件，一部分用于本控件\n     *\n     * @protected\n     * @method module:ui/layer/wrapper/layer._$$LayerWrapper#__doFilterOptions\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Object} 过滤后的配置参数\n     */\n    _pro.__doFilterOptions = function(_options){\n        var _result = {};\n        _u._$loop(_options,\n            function(_item,_key){\n                this.__lopt.hasOwnProperty(_key)\n                ? this.__lopt[_key] = _item\n                : _result[_key] = _item;\n            },this);\n        return _result;\n    };\n    /**\n     * 初始化弹层控件可选配置参数\n     *\n     * @protected\n     * @method module:ui/layer/wrapper/layer._$$LayerWrapper#__doInitLayerOptions\n     * @return {Void}\n     */\n    _pro.__doInitLayerOptions = function(){\n        this.__lopt = {\n            clazz:''\n           ,parent:null\n           ,content:this.__body\n           ,destroyable:!1\n           ,oncontentready:null\n           ,nohack:!1\n        };\n    };\n    /**\n     * 显示弹层\n     *\n     * 脚本举例\n     * ```javascript\n     * // 显示浮层\n     * _ly._$show();\n     * ```\n     *\n     * @method module:ui/layer/wrapper/layer._$$LayerWrapper#_$show\n     * @return {Void}\n     */\n    _pro._$show = function(){\n        if (!!this.__layer)\n            this.__layer._$show();\n        this._$dispatchEvent('onaftershow');\n    };\n    /**\n     * 隐藏弹层\n     *\n     * 脚本举例\n     * ```javascript\n     * // 隐藏弹层\n     * _ly._$hide();\n     * ```\n     *\n     * @method module:ui/layer/wrapper/layer._$$LayerWrapper#_$hide\n     * @return {Void}\n     */\n    _pro._$hide = function(){\n        if (!!this.__layer)\n            this.__layer._$hide();\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/layer/wrapper/window.js",
    "content": "/*\n * ------------------------------------------\n * 弹出窗体封装基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/layer/wrapper/window */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'ui/layer/wrapper/layer',\n    'ui/layer/window'\n],function(NEJ,_k,_i0,_i1,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 弹出窗体封装基类对象，主要实现层里面内容部分的业务逻辑\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/klass',\n     *     'util/template/tpl',\n     *     'ui/layer/wrapper/window',\n     *     'text!./mywindow.html'\n     * ],function(_k,_t,_l,_html,_p,_o,_f,_r){\n     *     var _pro;\n     *     // 第一步：继承此类，生成一个新类\n     *     _p._$$MyWindow = _k._$klass();\n     *     _pro = _p._$$MyWindow._$extend(_l._$$WindowWrapper);\n     *     // 生成窗体的展示内容\n     *     _pro.__initXGui = (function(){\n     *         var _seed_html = _t._$addNodeTemplate(_html);\n     *         return function(){\n     *             this.__seed_html = _seed_html;\n     *         };\n     *     }\n     * })();\n     *\n     * NEJ.define([\n     *     '/path/custom/to/mywindow.js'\n     * ],function(_i0,_p,_o,_f,_r){\n     *     // 第二步:实例化一个窗体控件\n     *     var _myCard = _i0._$$MyWindow._$allocate({\n     *         parent:document.body,\n     *         title:'窗口标题',\n     *         draggable:false,\n     *         // 是否有盖层\n     *         mask:true,\n     *         onclose:function(){\n     *           // 关闭窗口的回调\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @class   module:ui/layer/wrapper/window._$$WindowWrapper\n     * @extends module:ui/layer/wrapper/layer._$$LayerWrapper\n     * @param   {Object} arg0 - 可选配置参数\n     *\n     */\n    _p._$$WindowWrapper = _k._$klass();\n    _pro = _p._$$WindowWrapper._$extend(_i0._$$LayerWrapper);\n    /**\n     * 构建弹层控件实例，子类实现具体业务逻辑\n     *\n     * @protected\n     * @method module:ui/layer/wrapper/window._$$WindowWrapper#__getLayerInstance\n     * @return {module:ui/layer/layer._$$Layer} 弹层控件实例\n     */\n    _pro.__getLayerInstance = function(){\n        return _i1._$$Window._$allocate(this.__lopt);\n    };\n    /**\n     * 初始化弹层控件可选配置参数\n     *\n     * @protected\n     * @method module:ui/layer/wrapper/window._$$WindowWrapper#__doInitLayerOptions\n     * @return {Void}\n     */\n    _pro.__doInitLayerOptions = function(){\n        this.__super();\n        this.__lopt.mask  = null;\n        this.__lopt.title = '标题';\n        this.__lopt.align = '';\n        this.__lopt.draggable = !1;\n        this.__lopt.onclose = null;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/lightbox/demo/lightbox.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - LightBox</title>\n    <meta charset=\"utf-8\" />\n    <style>\n        *{margin:0;padding:0;border:0;}\n        html,body{width:100%;height:100%;}\n    </style>\n  </head>\n  <body>\n    \n    <script>window.NEJ_CONF={root:'../../../../res/'};</script>\n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            '../lightbox.js'\n        ],function(_i){\n            _i._$$LightBox._$allocate({\n                parent:document.body,\n                list:[\n                    {title:'汽车1',src:'http://www0.autoimg.cn/newspic/2014/11/5/620x0_0_2014110510432141064.jpg'},\n                    {title:'汽车2',src:'http://car0.autoimg.cn/carnews/2014/11/5/d_20141105071745705345010.jpg'},\n                    {title:'汽车3',src:'http://car1.autoimg.cn/carnews/2014/11/5/d_20141105071823084345010.jpg'},\n                    {title:'汽车4',src:'http://car0.autoimg.cn/carnews/2014/11/5/d_20141105071820932345010.jpg'},\n                    {title:'汽车5',src:'http://car0.autoimg.cn/carnews/2014/11/5/d_20141105071756548345010.jpg'},\n                    {title:'汽车6',src:'http://car1.autoimg.cn/carnews/2014/11/5/d_20141105092940897345011.jpg'},\n                    {title:'汽车7',src:'http://car1.autoimg.cn/carnews/2014/11/5/d_20141105071754832345010.jpg'},\n                    {title:'汽车8',src:'http://car0.autoimg.cn/carnews/2014/11/5/d_20141105071818090345011.jpg'}\n                ]\n            });\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/ui/lightbox/lightbox.css",
    "content": ".#<uispace>-mask{position:fixed;_position:absolute;z-index:5000;top:0;bottom:0;left:0;right:0;width:100%;height:100%;background:#aaa;}\n.#<uispace>{position:fixed;_position:absolute;z-index:5001;background:#fff;text-align:center;$<vendor>transition-duration:300ms;}\n.#<uispace> .zbtn{position:absolute;cursor:pointer;width:24px;height:24px;line-height:24px;border:2px solid #fff;background:#333;color:#fff;$<vendor>border-radius:50%;font-weight:bold;}\n.#<uispace> .zcls{top:-12px;right:-12px;}\n.#<uispace> .zbtn{opacity:0;*filter:alpha(opacity=0);$<vendor>transition-duration:300ms;$<vendor>transition-property:opacity;}\n.#<uispace> .zprv{left:5px;}\n.#<uispace> .znxt{right:5px;}\n.#<uispace> .ztrp{position:absolute;left:0;right:0;bottom:0;width:100%;}\n.#<uispace> .zshw{display:block;width:100%;height:100%;}\n.#<uispace>:hover .zbtn{opacity:1;*filter:alpha(opacity=100);}\n.#<uispace> .js-disabled,.#<uispace>.js-loading .zbpt{visibility:hidden;}\n"
  },
  {
    "path": "src/ui/lightbox/lightbox.html",
    "content": "<div>\n  <span class=\"zbtn zcls\" data-action=\"close\" title=\"关闭\">×</span>\n  <span class=\"zbtn zbpt zprv j-zflag\" data-action=\"prev\" title=\"上一张\">&lt;</span>\n  <span class=\"zbtn zbpt znxt j-zflag\" data-action=\"next\" title=\"下一张\">&gt;</span>\n  <img class=\"zshw j-zflag\"/>\n  <div class=\"ztrp\">\n    <div class=\"zttl j-zflag\"></div>\n  </div>\n</div>"
  },
  {
    "path": "src/ui/lightbox/lightbox.js",
    "content": "/*\n * ------------------------------------------\n * 图片幻灯片控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/lightbox/lightbox */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/constant',\n    'base/element',\n    'base/event',\n    'util/template/tpl',\n    'ui/base',\n    'text!./lightbox.css',\n    'text!./lightbox.html'\n],function(NEJ,_k,_g,_e,_v,_t,_i,_css,_html,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 图片幻灯片控件\n     * \n     * ```javascript\n     *  NEJ.define([\n     *      'ui/lightbox/lightbox'\n     *  ],function(_i){\n     *      _i._$$LightBox._$allocate({\n     *          parent:document.body,\n     *          list:[\n     *              {title:'汽车1',src:'./1.jpg'},\n     *              {title:'汽车2',src:'./2.jpg'},\n     *              {title:'汽车3',src:'./3.jpg'},\n     *              {title:'汽车4',src:'./4.jpg'},\n     *              {title:'汽车5',src:'./5.jpg'},\n     *              {title:'汽车6',src:'./6.jpg'},\n     *              {title:'汽车7',src:'./7.jpg'},\n     *              {title:'汽车8',src:'./8.jpg'}\n     *          ]\n     *      });\n     *  });\n     * ```\n     *\n     * @class    module:ui/lightbox/lightbox._$$LightBox\n     * @extends  module:ui/base._$$Abstract\n     * \n     * @param    {Object} config   - 配置参数\n     * @property {String} mask     - 遮罩样式名称\n     * @property {String} loading  - 图片加载中样式名称，默认为js-loading\n     * @property {String} disabled - 按钮禁用样式名称，默认为js-disabled\n     * @property {Array}  list     - 图片数据列表，[{src:'xxx',title:'xxx'},...]\n     * @property {Number} index    - 当前显示图片索引\n     */\n    _p._$$LightBox = _k._$klass();\n    _pro = _p._$$LightBox._$extend(_i._$$Abstract);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/lightbox/lightbox._$$LightBox#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__ilist = _options.list||_r;\n        this.__discs = _options.disabled||'js-disabled';\n        this.__loading = _options.loading||'js-loading';\n        _e._$addClassName(this.__mask,_options.mask);\n        // init event\n        this.__doInitDomEvent([[\n            this.__body,'click',\n            this.__onAction._$bind(this)\n        ],[\n            document,'click',\n            this.__doClose._$bind(this)\n        ],[\n            this.__test,'load',\n            this.__onImageLoad._$bind(this,!0)\n        ],[\n            this.__test,'error',\n            this.__onImageLoad._$bind(this,!1)\n        ]]);\n        this.__body.insertAdjacentElement(\n            'beforeBegin',this.__mask\n        );\n        this.__doUpdateIndex(_options.index);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/lightbox/lightbox._$$LightBox#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        delete this.__ilist;\n        _e._$removeByEC(this.__mask);\n        this.__mask.className = this.__seed_css+'-mask';\n        var _blank = _g._$BLANK_IMAGE;\n        this.__image.src = _blank;\n        this.__test.src = _blank;\n        this.__super();\n    };\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/lightbox/lightbox._$$LightBox#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = (function(){\n        var _seed_css = _e._$pushCSSText(_css),\n            _seed_html= _t._$addNodeTemplate(_html);\n        return function(){\n            this.__seed_css  = _seed_css;\n            this.__seed_html = _seed_html;\n        };\n    })();\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method module:ui/lightbox/lightbox._$$LightBox#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        this.__test = _e._$create('img');\n        this.__mask = _e._$create(\n            'div',this.__seed_css+'-mask'\n        );\n        _e._$setStyle(this.__mask,'opacity',0.7);\n        // 0 - previous button\n        // 1 - next button\n        // 2 - image show\n        // 3 - image title\n        var _list = _e._$getByClassName(\n            this.__body,'j-zflag'\n        );\n        this.__nprev = _list[0];\n        this.__nnext = _list[1];\n        this.__image = _list[2];\n        this.__title = _list[3];\n    };\n    /**\n     * 关闭幻灯片\n     * \n     * @protected\n     * @method module:ui/lightbox/lightbox._$$LightBox#__doClose\n     * @return {Void}\n     */\n    _pro.__doClose = function(){\n        this._$recycle();\n    };\n    /**\n     * 更新索引值\n     * \n     * @protected\n     * @method module:ui/lightbox/lightbox._$$LightBox#__doUpdateIndex\n     * @param  {Number} arg0 - 索引值\n     * @return {Void}\n     */\n    _pro.__doUpdateIndex = function(_index){\n        this.__index = parseInt(_index)||0;\n        this.__doSyncBtnState();\n        this.__doSyncImageData(\n            this.__ilist[this.__index]\n        );\n    };\n    /**\n     * 同步按钮状态\n     * \n     * @protected\n     * @method module:ui/lightbox/lightbox._$$LightBox#__doSyncBtnState\n     * @return {Void}\n     */\n    _pro.__doSyncBtnState = function(){\n        // previous button\n        this.__index<=0 \n        ? _e._$addClassName(this.__nprev,this.__discs)\n        : _e._$delClassName(this.__nprev,this.__discs);\n        // next button\n        this.__index>=this.__ilist.length-1\n        ? _e._$addClassName(this.__nnext,this.__discs)\n        : _e._$delClassName(this.__nnext,this.__discs);\n    };\n    /**\n     * 同步图片数据\n     * \n     * @protected\n     * @method module:ui/lightbox/lightbox._$$LightBox#__doSyncImageData\n     * @param  {Object} arg0 - 图片数据，如{src:'xxxxx',title:'xxxxxxxx'}\n     * @return {Void}\n     */\n    _pro.__doSyncImageData = function(_data){\n        _data = _data||_o;\n        this.__title.innerText = _data.title;\n        //_e._$setStyle(this.__image,'opacity',0);\n        _e._$addClassName(this.__body,this.__loading);\n        this.__test.src = _data.src||_g._$BLANK_IMAGE;\n    };\n    /**\n     * 图片载入回调\n     * \n     * @protected\n     * @method module:ui/lightbox/lightbox._$$LightBox#__onImageLoad\n     * @return {Void}\n     */\n    _pro.__onImageLoad = function(_isok){\n        _e._$delClassName(this.__body,this.__loading);\n        // load blank\n        if (this.__test.src.indexOf(_g._$BLANK_IMAGE)>=0){\n            return;\n        }\n        // dump image info\n        var _url = this.__test.src,\n            _pbox = _e._$getPageBox(),\n            _sbox = _e._$getMaxBox({\n                width:this.__test.naturalWidth||this.__test.width,\n                height:this.__test.naturalHeight||this.__test.height\n            },{\n                width:_pbox.clientWidth*0.85,\n                height:_pbox.clientHeight*0.85\n            }),\n            _mbox = _e._$align({\n                width:_pbox.clientWidth,\n                height:_pbox.clientHeight\n            },_sbox);\n        this.__test.src = _g._$BLANK_IMAGE;\n        // update button position\n        _e._$setStyle(\n            this.__nprev,'top',\n            (_sbox.height-this.__nprev.offsetHeight)/2+'px'\n        );\n        _e._$setStyle(\n            this.__nnext,'top',\n            (_sbox.height-this.__nnext.offsetHeight)/2+'px'\n        );\n        // update image show\n        _e._$style(\n            this.__body,{\n                top:_mbox.top+'px',\n                left:_mbox.left+'px',\n                width:_sbox.width+'px',\n                height:_sbox.height+'px'\n            }\n        );\n        //_e._$setStyle(this.__image,'opacity',1);\n        this.__image.src = _url;\n    };\n    /**\n     * 操作行为\n     * \n     * @protected\n     * @method module:ui/lightbox/lightbox._$$LightBox#__onAction\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onAction = function(_event){\n        _v._$stop(_event);\n        // check action\n        var _action = _e._$dataset(\n            _v._$getElement(\n                _event,'d:action'\n            ),'action'\n        );\n        if (!_action) return;\n        // do action\n        switch(_action){\n            case 'close':\n                this.__doClose();\n            break;\n            case 'prev':\n                if (!_e._$hasClassName(this.__nprev,this.__discs)){\n                    this.__doUpdateIndex(this.__index-1);\n                }\n            break;\n            case 'next':\n                if (!_e._$hasClassName(this.__nnext,this.__discs)){\n                    this.__doUpdateIndex(this.__index+1);\n                }\n            break;\n        }\n    };\n    \n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/mask/mask.css",
    "content": ".#<uispace>{position:fixed;_position:absolute;z-index:100;top:0;bottom:0;left:0;right:0;width:100%;height:100%;background-image:url(#<blankimage>);}"
  },
  {
    "path": "src/ui/mask/mask.js",
    "content": "/*\n * ------------------------------------------\n * 盖层控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/maks/mask */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/constant',\n    'base/element',\n    'base/util',\n    'ui/base',\n    'text!./mask.css'\n],function(NEJ,_k,_g,_e,_u,_i,_css,_p,_o,_f,_r){\n    var _pro,\n        _seed_css = _e._$pushCSSText(_css,{blankimage:_g._$BLANK_IMAGE});\n    /**\n     * 盖层控件\n     *\n     * 页面结构举例\n     * ```html\n     * <style type=\"text/css\">\n     *     .box{position:relative;}\n     * </style>\n     * <div id=\"mask-box\" class=\"box\"></div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'ui/maks/mask'\n     * ],function(_i0,_p,_o,_f,_r){\n     *     var _mask = _i0._$$Mask._$allocate({\n     *         parent:document.body,\n     *         content:'<div style=\"width:100px;height:100px;margin:0 auto;margin-top:150px;\">搞一点盖层的内容</div>'\n     *     });\n     * });\n     * ```\n     *\n     * @class     module:ui/maks/mask._$$Mask\n     * @extends   module:ui/base._$$Abstract\n     * @param     {Object}      arg0    - 可选配置参数\n     * @property  {String|Node} content - 内容节点或者HTML代码\n     */\n    _p._$$Mask = _k._$klass();\n    _pro = _p._$$Mask._$extend(_i._$$Abstract);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/maks/mask._$$Mask#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        var _content = _options.content||'&nbsp;';\n        _u._$isString(_content)\n        ? this.__body.innerHTML = _content\n        : this.__body.appendChild(_content);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/maks/mask._$$Mask#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        this.__body.innerHTML = '&nbsp;';\n    };\n    /**\n     * 初始化外观\n     *\n     * @protected\n     * @method module:ui/maks/mask._$$Mask#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css = _seed_css;\n    };\n    /**\n     * 显示盖层\n     *\n     * ```javascript\n     * // 先隐藏盖层\n     * _mask._$hide();\n     * // 显示盖层\n     * _mask._$show();\n     * ```\n     *\n     * @method module:ui/maks/mask._$$Mask#_$show\n     * @return {Void}\n     */\n    _pro._$show = function(){\n        _e._$fullScreen(this.__body);\n        this.__super();\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/mask/test/mask.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>mask测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style type=\"text/css\">\n\t\t\t.box{position:relative;}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit mask test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<div id=\"mask-box\" class=\"box\"></div>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./mask.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/ui/mask/test/mask.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"ui-mask\");\n\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _p = _('nej.ui');\n\n    //开始单元测试\n    test('mask',function(){\n        expect(0);\n        var _mask = _p._$$Mask._$allocate({\n            parent:document.body,\n            content:'<div style=\"width:100px;height:100px;margin:0 auto;margin-top:150px;\">搞一点盖层的内容</div>'\n        });\n\t\t_mask._$hide();\n\t\t_mask._$show();\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}mask.test.js',['ui/mask/mask'],f);\n});"
  },
  {
    "path": "src/ui/pager/base.css",
    "content": ".#<uispace>{font-size:12px;line-height:160%;}\n.#<uispace> a{margin:0 2px;padding:2px 8px;color:#333;border:1px solid #aaa;text-decoration:none;}\n.#<uispace> .js-disabled{cursor:default;}\n.#<uispace> .js-selected{cursor:default;background-color:#bbb;}"
  },
  {
    "path": "src/ui/pager/base.js",
    "content": "/*\n * ------------------------------------------\n * 分页器控件基类封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/pager/base */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/util',\n    'ui/base',\n    'util/template/jst',\n    'text!./base.css'\n],function(NEJ,_k,_e,_u,_i,_t0,_css,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 分页器控件基类封装\n     *\n     * 页面结构举例\n     * ```html\n     *   <div id=\"pagerCnt\">page</div>\n     *   <div id=\"pagerCnt2\">page</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'base/klass',\n     *       'ui/pager/pager.base',\n     *       'util/page/page'\n     *   ],function(_k,_u,_t,_p,_o,_f,_r){\n     *       // 第一步：继承此类，新建一个子类\n     *       _p._$$Pager = _k._$klass();\n     *       _pro = _p._$$Pager._$extend(_u._$$AbstractPager);\n     *\n     *      // 调用父类reset方法后，\n     *   实例化一个_t._$page对象，首尾页用数字表示\n     *       // 表现为,上一页 1 2 3.. 10 下一页\n     *       // 或者实例化一个page.simple对象，首尾页需要辅助，数字可能不会出现\n     *       // 表现为,首页 上一页 5 6 7 8 9 10 下一页 末页\n     *       _pro.__reset = function(_options){\n     *           this.__super(_options);\n     *           this.__page = _t._$$PageFragment._$allocate(this.__popt);\n     *           };\n     *\n     *      // reset之前生成需要的页码结构\n     *      _pro.__initNode = function(){\n     *\n     *      };\n     *\n     *      // reset之前生成需要的页码结构\n     *      _pro.__initNodeTemplate = function(){\n     *          // _seed_html根据需求定制\n     *          this.__seed_html = _seed_html;\n     *      };\n     *      return _p;\n     *   })\n     *\n     *   NEJ.define([\n     *       '/path/to/custom/pager.js'\n     *   ],function(_u,_p,_o,_f,_r){\n     *       // 第二步：生成一个pager实例\n     *       // 总页数10，默认第一页\n     *       var _pager = _u._$$Pager._$allocate({\n     *           parent:'pagerCnt',\n     *           onchange: function(_event){},\n     *           total: 10,\n     *           index:1\n     *       });\n     *   })\n     * ```\n     *\n     * @class     module:ui/pager/base._$$AbstractPager\n     * @extends   module:ui/base._$$Abstract\n     * @param     {Object} arg0   - 可选配置参数\n     * @property  {Number} index  - 当前页码\n     * @property  {Number} total  - 总页码数\n     * @property  {Number} number - 显示页数\n     * @property  {Number} limit  - 总页数限制\n     * @property  {Object} label  - 按钮文案，{prev:'&lt;',next:'&gt;'}\n     */\n    /**\n     * 页码切换事件，输入{last:3,index:1,total:12}\n     *\n     * @event    module:ui/pager/base._$$AbstractPager#onchange\n     * @param    {Object} arg0  - 页码状态对象\n     * @property {Number} last  - 上一次的页码\n     * @property {Number} index - 当前要切换的页面\n     * @property {Number} total - 总页面数\n     *\n     */\n    _p._$$AbstractPager = _k._$klass();\n    _pro = _p._$$AbstractPager._$extend(_i._$$Abstract);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/pager/base._$$AbstractPager#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__bopt = _u._$merge({},_options);\n        this.__popt = _u._$merge({},_options);\n        delete this.__bopt.onchange;\n        this.__popt.onchange =\n            this.__onChange._$bind(this);\n        this.__super(_options);\n        this.__doResetNumber(_options);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/pager/base._$$AbstractPager#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        if (!!this.__page){\n            this.__page._$recycle();\n            delete this.__page;\n        }\n        this.__super();\n        delete this.__bopt;\n        delete this.__popt;\n        this._$unbind();\n        this.__body.innerHTML = '&nbsp;';\n    };\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/pager/base._$$AbstractPager#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = (function(){\n        var _seed_css = _e._$pushCSSText(_css);\n        return function(){\n            this.__seed_css  = _seed_css;\n        };\n    })();\n    /**\n     * 重置页码数\n     *\n     * @protected\n     * @method module:ui/pager/base._$$AbstractPager#__doResetNumber\n     * @return {Void}\n     */\n    _pro.__doResetNumber = function(_data){\n        var _label = _data.label||_o;\n        // previous button\n        if (!_data.noprv){\n            this.__popt.pbtn = _e._$create(\n                'a','zbtn zprv',this.__body\n            );\n            this.__popt.pbtn.innerHTML = _label.prev||'上一页';\n        }\n        // page show\n        var _arr = [];\n        for(var i=1,l=_data.number;i<=l;i++){\n            _arr.push(_e._$create(\n                'a','zpgi zpg'+i,this.__body\n            ));\n        }\n        this.__popt.list = _arr;\n        // next button\n        if (!_data.nonxt){\n            this.__popt.nbtn = _e._$create(\n                'a','zbtn znxt',this.__body\n            );\n            this.__popt.nbtn.innerHTML = _label.next||'下一页';\n        }\n    };\n    /**\n     * 页面变化触发事件\n     *\n     * @protected\n     * @method module:ui/pager/base._$$AbstractPager#__onChange\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onChange = function(_event){\n        if (this.__flag) return;\n        var _index = _event.index,\n            _total = _event.total;\n        // sync pagers\n        this.__flag = !0;\n        this._$updatePage(_index,_total);\n        _u._$forEach(this.__binders,\n            function(_pager){\n                _pager._$updatePage(_index,_total);\n            });\n        this.__flag = !1;\n        this._$dispatchEvent('onchange',_event);\n    };\n    /**\n     * 绑定联动分页器\n     *\n     * 脚本举例\n     * ```javascript\n     * // 绑定一个联动翻页器\n     * _pager._$bind('pagerCnt2')\n     * ```\n     *\n     * @method module:ui/pager/base._$$AbstractPager#_$bind\n     * @param  {String|Node} arg0 - 联动分页器父容器\n     * @return {Void}\n     */\n    _pro._$bind = function(_parent){\n        _parent = _e._$get(_parent);\n        if (!_parent) return;\n        var _opt = _u._$merge(\n            {},this.__bopt\n        );\n        _opt.parent = _parent;\n        _opt.index = this._$getIndex();\n        _opt.total = this._$getTotal();\n        var _pager = this.constructor._$allocate(_opt);\n        _pager._$setEvent('onchange',this.__popt.onchange);\n        if (!this.__binders) this.__binders = [];\n        this.__binders.push(_pager);\n    };\n    /**\n     * 解除联动分页器\n     *\n     * 脚本举例\n     * ```javascript\n     * // 解绑所以联动翻页器\n     * _pager._$unbind()\n     * ```\n     *\n     * @method module:ui/pager/base._$$AbstractPager#_$unbind\n     * @return {nej.ui._$$AbstractPager}\n     */\n    _pro._$unbind = (function(){\n        var _doRemove = function(_pager,_index,_list){\n            _pager._$recycle();\n            _list.splice(_index,1);\n        };\n        return function(){\n            _u._$reverseEach(this.__binders,_doRemove);\n        };\n    })();\n    /**\n     * 跳转至指定页码\n     *\n     * 脚本举例\n     * ```javascript\n     * // 设置页码到第二页\n     * _pager._$setIndex(2)\n     * ```\n     *\n     * @method module:ui/pager/base._$$AbstractPager#_$setIndex\n     * @param  {Number} arg0 - 页码\n     * @return {nej.ui._$$AbstractPager}\n     */\n    _pro._$setIndex = function(_index){\n        if (!this.__page) return;\n        this.__page._$setIndex(_index);\n    };\n    /**\n     * 取当前页码\n     *\n     * 脚本举例\n     * ```javascript\n     * // 取当前页码\n     * _pager._$getIndex()\n     * ```\n     *\n     * @method module:ui/pager/base._$$AbstractPager#_$getIndex\n     * @return {Number} 当前页码\n     */\n    _pro._$getIndex = function(){\n        if (!this.__page) return 1;\n        return this.__page._$getIndex();\n    };\n    /**\n     * 取总页数\n     *\n     * 脚本举例\n     * ```javascript\n     * // 取总页数\n     * _pager._$getTotal()\n     * ```\n     *\n     * @method module:ui/pager/base._$$AbstractPager#_$getTotal\n     * @return {Number} 总页数\n     */\n    _pro._$getTotal = function(){\n        if (!this.__page) return 1;\n        return this.__page._$getTotal();\n    };\n    /**\n     * 更新页码信息\n     *\n     * 脚本举例\n     * ```javascript\n     * // 重新设置默认页和总页数\n     * _pager._$updatePage(2,10);\n     * ```\n     *\n     * @method module:ui/pager/base._$$AbstractPager#_$updatePage\n     * @param  {Number} arg0 - 当前页码\n     * @param  {Number} arg1 - 总页码数\n     * @return {nej.ui._$$AbstractPager}\n     */\n    _pro._$updatePage = function(_index,_total){\n        if (!this.__page) return;\n        this.__page._$updatePage(_index,_total);\n    };\n    /**\n     * 更新总页数\n     *\n     * @method module:ui/pager/base._$$AbstractPager#_$updateTotal\n     * @param  {Number} arg0 - 总页数\n     * @return {Void}\n     */\n    _pro._$updateTotal = function(_total){\n        if (!this.__page) return;\n        this.__page._$updateTotal(_total);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/pager/demo/pager.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>demo for pager</title>\n    <meta charset=\"utf-8\" />\n    <style>\n        body{padding:50px;}\n    </style>\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n  </head>\n  <body>\n    <script src=\"../../../define.js\"></script>\n    <script>\n      NEJ.define([\n          '../pager.js'\n      ],function(_i){\n          var _pager = _i._$$Pager._$allocate({\n              index:3,\n              total:100,\n              parent:document.body,\n              onchange:function(_event){\n                  log('change page from '+_event.last+' to '+_event.index);\n              }\n          });\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/ui/pager/pager.base.js",
    "content": "// link to ui/pager/base for compatible\n// use ui/pager/base for new project\nNEJ.define(['./base.js'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/pager/pager.js",
    "content": "/*\n * ------------------------------------------\n * 分页器控件封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/pager/pager */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'ui/pager/base',\n    'util/page/page'\n],function(NEJ,_k,_e,_i0,_t0,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 分页器控件封装\n     *\n     * 页面结构举例\n     * ```html\n     *   <div id=\"pagerCnt\">page</div>\n     *   <div id=\"pagerCnt2\">page</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'ui/pager/pager'\n     *   ],function(_u,_p,_o,_f,_r){\n     *           // 默认第一页\n     *       var _setIndex = 1;\n     *       // 页面更改的回调方法\n     *       var _onchangeHandle = function(_obj){\n     *           var _index = _obj.index;\n     *       };\n     *       // 实例化一个pager对象，总共10页\n     *       var _pager = _u._$$Pager._$allocate({\n     *           parent:'pagerCnt',\n     *           onchange: _onchangeHandle,\n     *           total: 10,\n     *           index:_setIndex\n     *       });\n     *       // 从第2页翻到第10页\n     *       for(var i = 2 ; i < 11 ; i++){\n     *           _setIndex = i;\n     *           _pager._$setIndex(_setIndex);\n     *       }\n     *       // 绑定一个翻页器,视觉上翻页器会联动，\n     *       但最后触发一次翻页器的回调,避免重复触发\n     *       _pager._$bind('pagerCnt2');\n     *   })\n     * ```\n     *\n     * @class     module:ui/pager/pager._$$Pager\n     * @uses      module:util/page/page._$$PageFragment\n     * @extends   module:ui/base._$$Abstract\n     * @param     {Object}  arg0 - 可选配置参数\n     * @property  {Number}  index - 当前页码\n     * @property  {Number}  total - 总页码数\n     * @property  {Boolean} noend - 无尾页显示\n     */\n    /**\n     * 页码切换事件，输入{last:3,index:1,total:12}\n     *\n     * @event  module:ui/pager/pager._$$Pager#onchange\n     * @param  {Object}   arg0  - 页码状态对象\n     * @property {Number} last  - 上一次的页码\n     * @property {Number} index - 当前要切换的页面\n     * @property {Number} total - 总页面数\n     *\n     */\n    _p._$$Pager = _k._$klass();\n    _pro = _p._$$Pager._$extend(_i0._$$AbstractPager);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/pager/pager._$$Pager#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        _options.number =\n            parseInt(_options.number)||9;\n        this.__super(_options);\n        this.__page = _t0._$$PageFragment._$allocate(this.__popt);\n    };\n    /**\n     * 页面变化触发事件\n     *\n     * @protected\n     * @method module:ui/pager/pager._$$Pager#__onChange\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onChange = function(_event){\n        if (!!this.__bopt.noend){\n            var _dext = _event.ext||_o,\n                _list = _dext.list||_r;\n            if (_dext.last){\n                _e._$setStyle(\n                    _list[_list.length-1],\n                    'display','none'\n                );\n            }\n        }\n        this.__super(_event);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/pager/pager.simple.js",
    "content": "// link to ui/pager/simple for compatible\n// use ui/pager/simple for new project\nNEJ.define(['./simple.js'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/pager/simple.js",
    "content": "/*\n * ------------------------------------------\n * 分页器控件封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/pager/simple */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'ui/pager/base',\n    'util/page/simple'\n],function(NEJ,_k,_e,_i0,_t0,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 分页器控件封装<br />\n     * 页面结构举例\n     * ```html\n     *   <div id=\"pagerCnt\">page</div>\n     *   <div id=\"pagerCnt2\">page</div>\n     * ```\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'ui/pager/pager.simple'\n     *   ],function(_u,_p,_o,_f,_r){\n     *       // 默认第一页\n     *       var _setIndex = 1;\n     *       // 页面更改的回调方法\n     *       var _onchangeHandle = function(_obj){\n     *           var _index = _obj.index;\n     *       };\n     *       // 实例化一个pager对象，总共10页\n     *       var _pager = _u._$$Pager._$allocate({\n     *           parent:'pagerCnt',\n     *           onchange: _onchangeHandle,\n     *           total: 10,\n     *           index:_setIndex\n     *       });\n     *       // 从第2页翻到第10页\n     *       for(var i = 2 ; i < 11 ; i++){\n     *           _setIndex = i;\n     *           _pager._$setIndex(_setIndex);\n     *       }\n     *       // 绑定一个翻页器,视觉上翻页器会联动，\n     *       但最后触发一次翻页器的回调,避免重复触发\n     *       _pager._$bind('pagerCnt2');\n     *   })\n     * ```\n     *\n     * @class     module:ui/pager/simple._$$Pager\n     * @uses      module:util/page/page._$$PageFragment\n     * @extends   module:ui/base._$$Abstract\n     * @param     {Object} arg0  - 可选配置参数\n     * @property  {Number} index - 当前页码\n     * @property  {Number} total - 总页码数\n     */\n    /**\n     * 页码切换事件，输入{last:3,index:1,total:12}\n     *\n     * @event    module:ui/pager/simple._$$SimplePager#onchange\n     * @param    {Object} arg0  - 页码状态对象\n     * @property {Number} last  - 上一次的页码\n     * @property {Number} index - 当前要切换的页面\n     * @property {Number} total - 总页面数\n     *\n     */\n    _p._$$SimplePager = _k._$klass();\n    _pro = _p._$$SimplePager._$extend(_i0._$$AbstractPager);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/pager/simple._$$SimplePager#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        _options.number =\n            parseInt(_options.number)||1;\n        if (_options.total==null)\n            _options.total = 10000;\n        this.__super(_options);\n        this.__page = _t0._$$PageSimple._$allocate(this.__popt);\n    };\n    /**\n     * 重置页码数\n     *\n     * @protected\n     * @method module:ui/pager/simple._$$SimplePager#__doResetNumber\n     * @return {Void}\n     */\n    _pro.__doResetNumber = function(_data){\n        var _label = _data.label||_o;\n        // begin page\n        if (!!_data.beg){\n            this.__popt.sbtn = _e._$create(\n                'a','zbtn zbeg',this.__body\n            );\n            this.__popt.sbtn.innerHTML = _label.beg||'首页';\n        }\n        // page list and prev and next\n        this.__super(_data);\n        // end page\n        if (!!_data.end){\n            this.__popt.ebtn = _e._$create(\n                'a','zbtn zend',this.__body\n            );\n            this.__popt.ebtn.innerHTML = _label.end||'尾页';\n        }\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/pager/test/pager.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>pager测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style type=\"text/css\">\n\t\t\t.js-selected{color:pink;}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit pager test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<div id=\"pagerCnt\">page</div>\n\t\t<div id=\"pagerCnt2\">page</div>\n\t\t<div id=\"pagerCnt3\">page</div>\n\t\t<div id=\"page\">\n\t\t\t<a href=\"#\" class=\"zbtn sbtn\">首页</a>\n\t        <a href=\"#\" class=\"zbtn zprv\">上一页</a>\n            <a href=\"#\" class=\"zpgi\"></a>\n\t\t\t<a href=\"#\" class=\"zpgi\"></a>\n\t\t\t<a href=\"#\" class=\"zpgi\"></a>\n\t\t\t<a href=\"#\" class=\"zpgi\"></a>\n            <a href=\"#\" class=\"zpgi\"></a>\n            <a href=\"#\" class=\"zpgi\"></a>\n\t\t\t<a href=\"#\" class=\"zpgi\"></a>\n            <a href=\"#\" class=\"zpgi\"></a>\n            <a href=\"#\" class=\"zpgi\"></a>\n            <a href=\"#\" class=\"zbtn znxt\">下一页</a>\n\t\t\t<a href=\"#\" class=\"zbtn ebtn\">末页</a>\n\t\t</div>\n\t\t<div id=\"pagebox\">\n            <a href=\"#\" class=\"zbtn zprv\">上一页</a>\n            <a href=\"#\" class=\"zpgi\"></a>\n            <a href=\"#\" class=\"zpgi\"></a>\n            <a href=\"#\" class=\"zpgi\"></a>\n            <a href=\"#\" class=\"zpgi\"></a>\n            <a href=\"#\" class=\"zpgi\"></a>\n            <a href=\"#\" class=\"zpgi\"></a>\n            <a href=\"#\" class=\"zpgi\"></a>\n            <a href=\"#\" class=\"zpgi\"></a>\n            <a href=\"#\" class=\"zpgi\"></a>\n            <a href=\"#\" class=\"zbtn znxt\">下一页</a>\n\t\t</div>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./pager.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/ui/pager/test/pager.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"pager\");\n    var p = NEJ.P('nej.ui'),\n        v = NEJ.P('nej.v'),\n\t\tt = NEJ.P('nej.ut'),\n\t\te = NEJ.P('nej.e');\n    //开始单元测试\n\n    test('实例化一个翻页器，并测试放回的页码是否一致', function() {\n        var _parent = document.getElementById('pagerCnt');\n        var _setIndex = 1;\n        var _onchangeHandle = function(_obj){\n            var _index = _obj.index;\n            equal(_index,_setIndex,'设置的页码数一致');\n        };\n        stop();\n        var _pager = p._$$Pager._$allocate({\n            parent:_parent,\n            onchange: _onchangeHandle,\n            total: 10,\n            index:1\n        });\n        for(var i = 2 ; i < 11 ; i++){\n            _setIndex = i;\n            _pager._$setIndex(_setIndex);\n        }\n        start();\n    });\n\n    test('关联一个翻页器',function(){\n        stop();\n        var _parent = document.getElementById('pagerCnt2');\n        var _setIndex = 1,_setIndex2 = 1;\n        var _onchangeHandle = function(_obj){\n            var _index = _obj.index;\n            if(_index == 1)//初始化页不用测试\n                return;\n            var _pnt1 = document.getElementById('pagerCnt2');\n            var _pnt2 = document.getElementById('pagerCnt3');\n            if(_index == 10){\n                equal(_pnt2.children.length,0,'解绑后翻页器从页面回收');\n                return;\n            }\n            var _children1 = _pnt1.children[0].children;\n            var _children2 = _pnt2.children[0].children;\n            var i = _index;\n            if(_children1[i].className.match('js-selected') == null)\n                return;\n            if(i == _children1.length - 2)\n                notEqual(_children1[i].className,_children2[i].className,'解绑后联动翻页器的表现形式不一致')\n            else\n                equal(_children1[i].className,_children2[i].className,'联动翻页器的表现形式一致，但最后触发一次翻页器的回调');\n        };\n        var _pager = p._$$Pager._$allocate({\n            parent:_parent,\n            onchange: _onchangeHandle,\n            total: 10,\n            index:1\n        });\n        var _parent2 = document.getElementById('pagerCnt3');\n        var _onchangeHandle2 = function(_index2){\n            _setIndex2 = _index2;\n        };\n        _pager._$bind(_parent2);\n        for(var i = 2 ; i < 11 ; i++){\n            _setIndex = i;\n            //最后一个解绑\n            if(i == 10)\n                _pager._$unbind();\n            _pager._$setIndex(_setIndex);\n        }\n        start();\n    });\n\n\ttest('util page.simple',function(){\n\t\tvar _page = e._$get('page');\n\t\tvar _ps = t._$$PageSimple._$allocate({\n\t\t\tlist:e._$getByClassName(_page,'zpgi'),\n\t\t\tevent:'click',\n\t\t\tpbtn:e._$getByClassName(_page,'zprv')[0],\n\t\t\tnbtn:e._$getByClassName(_page,'znxt')[0],\n\t\t\tsbtn:e._$getByClassName(_page,'sbtn')[0],\n\t\t\tebtn:e._$getByClassName(_page,'ebtn')[0],\n\t\t\tindex:90,\n\t\t\ttotal:100,\n\t\t\tonchange:function(_obj){\n\t\t\t\tok(true,'last page is :' + _obj.last + ' index page is:' + _obj.index + 'total:' + _obj.total)\n\t\t\t}\n\t\t});\n\t});\n\n\ttest('util page',function(){\n\t\tstop();\n\t\tvar _box = e._$get('pagebox');\n\t\tvar _pg = e._$page(_box,{\n            event:'click',\n            index:9,\n            total:10,\n            onchange:function(_obj){\n                ok(true,'last page is :' + _obj.last + ' index page is:' + _obj.index + 'total:' + _obj.total)\n                start();\n\t\t\t}\n\t\t});\n\t\t_pg._$setIndex(10);\n\t\t_pg._$setTotal(20);\n\t\t_pg._$updatePage(5,10);\n    });\n\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}pager.test.js',\n    ['ui/pager/pager',\n     'util/page/page.simple',\n     'util/page/page'],f);\n});\n"
  },
  {
    "path": "src/ui/portrait/complex.css",
    "content": ".#<uispace>{width:410px;border:1px;font-size:12px;text-align:center;}\n.#<uispace>,.#<uispace> .zbrd{border-style:solid;border-color:#aaa;}\n.#<uispace> a{text-decoration:none;}\n.#<uispace> .zbgp{background:url(#<portrait>btn.png) no-repeat;}\n.#<uispace> .zsdb{float:right;width:80px;text-align:left;}\n.#<uispace> .zsdb .zpgr{text-align:center;}\n.#<uispace> .zsdb .zpgr span{display:block;height:24px;margin:0 10px;border-color:#eee;cursor:pointer;}\n.#<uispace> .zsdb .zpup span{border-width:0 0 1px;background-position:center 2px;}\n.#<uispace> .zsdb .zpdn span{border-width:1px 0 0;background-position:center -18px;}\n.#<uispace> .zsdb .zwin{position:relative;height:180px;overflow:hidden;}\n.#<uispace> .zsdb .zlst{position:absolute;top:0;left:0;width:100%;}\n.#<uispace> .zsdb .zlst .zitm{height:22px;line-height:22px;padding-left:5px;border-width:0;}\n.#<uispace> .zsdb .zlst .zitm.js-selected{border-width:1px 0;margin-left:0;}\n.#<uispace> .zsdb .zbtn{display:block;margin-left:1px;color:#777;}\n.#<uispace> .zsdb .zbtn:hover,\n.#<uispace> .zsdb .zlst .zitm.js-selected{background-color:#e5e5e1;color:#000;text-decoration:none;}\n.#<uispace> .zsdb .js-disabled{cursor:default;}\n.#<uispace> .zsdb .js-disabled span{opacity:0.6;filter:alpha(opacity=60);cursor:default;}\n.#<uispace> .zsdb .js-disabled:hover{background-color:transparent;}\n.#<uispace> .zcnt{margin-right:79px;padding:5px 5px 0;border-width:0 1px 0 0;background:#e5e5e1;}\n.#<uispace> .zcnt .zptrt{border:none;}"
  },
  {
    "path": "src/ui/portrait/complex.html",
    "content": "<textarea name='ntp' id='#<mid>'>\n<div class=\"zbrd\">\n  <div class=\"zsdb\">\n    <a class=\"zbtn zpgr zpup j-flag\" href=\"#\" hidefocus=\"true\" title=\"上一页\"><span class=\"zbrd zbgp\">&nbsp;</span></a>\n    <div class=\"zwin\"><div class=\"zlst j-flag\"></div></div>\n    <a class=\"zbtn zpgr zpdn j-flag\" href=\"#\" hidefocus=\"true\" title=\"下一页\"><span class=\"zbrd zbgp\">&nbsp;</span></a>\n  </div>\n  <div class=\"zcnt zbrd j-flag\"></div>\n</div>\n</textarea>\n<textarea name='jst' id='#<lid>'>\n{list xlist as x}\n    <a href=\"#\" hidefoucus=\"true\" class=\"zbtn zitm zbrd\" data-value=\"${x.id}\">${x.name}</a>\n{/list}\n</textarea>"
  },
  {
    "path": "src/ui/portrait/complex.js",
    "content": "/*\n * ------------------------------------------\n * 复杂表情控件封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/portrait/complex */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/config',\n    'base/element',\n    'base/util',\n    'ui/base',\n    'ui/portrait/portrait',\n    'util/template/tpl',\n    'util/tab/tab',\n    'util/page/simple',\n    'util/data/portrait/portrait',\n    'util/template/jst',\n    'text!./complex.css',\n    'text!./complex.html'\n],function(NEJ,_k,_c,_e,_u,_i,_i0,_t0,_t2,_t3,_t4,_t5,_css,_html,_p,_o,_f,_r){\n    // variable declaration\n    var _pro,\n        _seed_css  = _e._$pushCSSText(\n            _css,{portrait:_c._$get('portrait')}\n        );\n    /**\n     * 复杂表情控件\n     *\n     * @class   module:ui/portrait/complex._$$ComplexPortrait\n     * @extends module:util/event._$$EventTarget\n     * @uses    module:ui/portrait/portait._$$Portrait\n     * @param   {Object} arg0 - 可选配置参数\n     */\n    /**\n     * 表情选中事件\n     *\n     * @event     module:ui/portrait/complex._$$ComplexPortrait#onselect\n     * @param     {Object} arg0 - 表情数据对象\n     * @property  {String} text - 表情描述\n     * @property  {String} url  - 表情文件地址\n     */\n    _p._$$ComplexPortrait = _k._$klass();\n    _pro = _p._$$ComplexPortrait._$extend(_i._$$Abstract);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:ui/portrait/complex._$$ComplexPortrait#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__popt = {\n            clazz:'zptrt',\n            cache:{\n                data:{},\n                klass:_t4._$$CachePortrait\n            }\n        };\n        this.__topt = {\n            offset:0,\n            limit:1000,\n            data:{type:'type'},\n            key:'portrait-type'\n        };\n        this.__bopt = {\n            onchange:this.__onTypeChange._$bind(this)\n        };\n        this.__copt = {\n            onlistload:this.__cbTypeListLoad._$bind(this)\n        };\n        this.__gopt = {\n            limit:8,\n            onchange:this.__onPageChange._$bind(this)\n        };\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/portrait/complex._$$ComplexPortrait#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__popt.onselect = _options.onselect;\n        delete _options.onselect;\n        this.__super(_options);\n        this.__cache = _t4._$$CachePortrait\n                         ._$allocate(this.__copt);\n        this.__cache._$getList(this.__topt);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/portrait/complex._$$ComplexPortrait#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__doClearComponent();\n        this.__super();\n    };\n    /**\n     * 初始化外观\n     *\n     * @protected\n     * @method module:ui/portrait/complex._$$ComplexPortrait#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = (function(){\n        var _seed = _t0._$parseUITemplate(_html);\n        return function(){\n            this.__seed_css = _seed_css;\n            this.__seed_html = _seed.mid;\n            this.__seed_list = _seed.lid;\n        };\n    })();\n    /**\n     * 初始化控件节点\n     *\n     * @protected\n     * @method module:ui/portrait/complex._$$ComplexPortrait#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        // 0 - previous type\n        // 1 - type list\n        // 2 - next type\n        // 3 - portrait list\n        var _list = _e._$getByClassName(this.__body,'j-flag');\n        this.__tbox = _list[1];\n        this.__gopt.pbtn = _list[0];\n        this.__gopt.nbtn = _list[2];\n        this.__popt.parent = _list[3];\n    };\n    /**\n     * 分类列表载入回调\n     *\n     * @protected\n     * @method module:ui/portrait/complex._$$ComplexPortrait#__cbTypeListLoad\n     * @return {Void}\n     */\n    _pro.__cbTypeListLoad = (function(){\n        var _inited = !1,\n            _limit = {\n                30:60,\n                60:15\n            };\n        var _doInit = function(_list){\n            if (_inited)\n                return;\n            _inited = !0;\n            var _arr = [];\n            _u._$forEach(\n                _list,function(_item){\n                    var _id = _item.id,\n                        _prefix = _c._$get('portrait')+_id+'/'+_id+'-',\n                        _total = Math.ceil(_item.total/_limit[_item.size]);\n                    for(var i=0;i<_total;i++){\n                        _arr.push('.'+_seed_css+' .js-'+_id+'-'+(i+1)+' .zitm{background-image:url('+_prefix+i+'.png);}');\n                    }\n                }\n            );\n            _e._$addStyle(_arr.join(''));\n        };\n        return function(_options){\n            var _list = this.__cache.\n                _$getListInCache(_options.key);\n            _doInit(_list);\n            _t5._$render(\n                this.__tbox,this.__seed_list,{\n                    xlist:_list\n                }\n            );\n            this.__gopt.total = Math.ceil(_list.length/this.__gopt.limit);\n            this.__pager = _t3._$$PageSimple._$allocate(this.__gopt);\n            this.__bopt.list = _e._$getChildren(this.__tbox);\n            this.__taber = _t2._$$Tab._$allocate(this.__bopt);\n        };\n    })();\n    /**\n     * 分类变化事件\n     *\n     * @protected\n     * @method module:ui/portrait/complex._$$ComplexPortrait#__onTypeChange\n     * @param  {Object} arg0 - 分类信息\n     * @return {Void}\n     */\n    _pro.__onTypeChange = function(_event){\n        if (!!this.__portrait){\n            this.__portrait._$recycle();\n        }\n        var _cache = this.__popt.cache,\n            _item = this.__cache._$getItemInCache(_event.data);\n        this.__popt.size = _item.size;\n        this.__popt.page = 'js-'+_item.id+'-';\n        _cache.lkey = 'portrait-'+_item.id;\n        _cache.data.type = _item.id;\n        this.__portrait = _i0._$$Portrait._$allocate(this.__popt);\n    };\n    /**\n     * 分类页码变化事件\n     *\n     * @protected\n     * @method module:ui/portrait/complex._$$ComplexPortrait#__onPageChange\n     * @param  {Object} arg0 - 页码信息\n     * @return {Void}\n     */\n    _pro.__onPageChange = function(_event){\n        var _offset = 0;\n        if (!!this.__taber){\n            var _list = this.__taber._$getList(),\n                _index = (_event.index-1)*this.__gopt.limit,\n                _offset = Math.max(0,_list[_index].offsetTop-2);\n            this.__taber._$go(_index);\n        }\n        _e._$setStyle(this.__tbox,'top',0-_offset+'px');\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/portrait/demo/complex.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test complex portrait</title>\n    <meta charset=\"utf-8\" />\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n  </head>\n  <body>\n    <script>\n        window.NEJ_CONF = {\n            portrait:'http://nej.netease.com/images/portrait/'\n        };\n    </script>\n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            '../complex.js'\n        ],function(_i){\n            \n            _i._$$ComplexPortrait._$allocate({\n                parent:document.body\n            });\n            \n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/ui/portrait/demo/simple.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test simple portrait</title>\n    <meta charset=\"utf-8\" />\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n  </head>\n  <body>\n    <script>\n        window.NEJ_CONF = {\n            portrait:'http://nej.netease.com/images/portrait/'\n        };\n    </script>\n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            '../simple.js'\n        ],function(_i){\n            \n            _i._$$SimplePortrait._$allocate({\n                parent:document.body\n            });\n            \n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/ui/portrait/portrait.complex.js",
    "content": "// link to ui/portrait/complex for compatible\n// use ui/portrait/complex for new project\nNEJ.define(['./complex.js'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/portrait/portrait.css",
    "content": ".#<uispace>{width:310px;padding:5px;background:#e5e5e1;border:1px solid #888;}\n.#<uispace> .zlst{position:relative;height:190px;}\n.#<uispace> .zlst .zitm{display:block;float:left;margin:-1px 0 0 -1px;text-indent:200px;overflow:hidden;border:1px solid #e5e5e1;cursor:pointer;background:no-repeat;}\n.#<uispace> .zlst .zitm:hover{position:relative;border-color:#000;zoom:1;}\n.#<uispace> .zlst .z30{width:30px;height:30px;line-height:30px;}\n.#<uispace> .zlst .z60{width:61px;height:60px;line-height:60px;}\n#<arrbg>\n.#<uispace> .zpbx{padding:5px 0 1px;text-align:right;}\n.#<uispace> .zpager .zbtn,.#<uispace> .zpager .zpgi{border:0;margin:0;}\n.#<uispace> .zpager .zpgi{display:none;}\n.#<uispace> .zpager .js-disabled{color:#777;}\n.#<uispace> .js-prev{position:absolute;top:0;left:0;background:#fff no-repeat center center;border:1px solid #888;}\n.#<uispace> .js-prev-30{width:60px;height:60px;}\n.#<uispace> .js-prev-30 img{display:none;}"
  },
  {
    "path": "src/ui/portrait/portrait.html",
    "content": "<textarea name='ntp' id='#<mid>'>\n<div>\n\t<div class=\"zlst j-flag\"></div>\n\t<div class=\"zpbx j-flag\"></div>\n</div>\n</textarea>\n<textarea name='jst' id='#<lid>'>\n{list beg..end as y}\n  {var x=xlist[y]}\n  <a href=\"#\" hidefocus=\"true\" class=\"zitm z${size} z${size}-${y%(row*col)}\" title=\"${x.text}\" data-id=\"${x.id}\" data-align=\"{if y%col<col/2}right{else}left{/if} top\">${x.text}</a>\n{/list}\n</textarea>"
  },
  {
    "path": "src/ui/portrait/portrait.js",
    "content": "/*\n * ------------------------------------------\n * 表情控件封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/portrait/portrait */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/constant',\n    'base/element',\n    'base/event',\n    'base/util',\n    'ui/base',\n    'ui/pager/pager.simple',\n    'util/list/module.pager',\n    'util/template/tpl',\n    'text!./portrait.css',\n    'text!./portrait.html'\n],function(NEJ,_k,_g,_e,_v,_u,_i,_i0,_t0,_t1,_css,_html,_p,_o,_f,_r){\n    // variable declaration\n    var _pro,\n        _seed_css = 'auto-'+_u._$uniqueID();\n    /**\n     * 表情控件\n     *\n     * @class     module:ui/portrait/portrait._$$Portrait\n     * @extends   module:ui/base._$$Abstract\n     * @param     {Object} arg0  - 可选配置参数\n     * @property  {Number} size  - 表情大小，30或60，默认为30， 目前支持30*30和60*60\n     * @property  {String} page  - 分页标识前缀，默认为js-page-\n     * @property  {Object} cache - 数据缓存配置\n     */\n    /**\n     * 表情选中事件\n     *\n     * @event     module:ui/portrait/portrait._$$Portrait#onselect\n     * @param     {Object} arg0 - 表情数据对象\n     * @property  {String} text - 表情描述\n     * @property  {String} url  - 表情文件地址\n     *\n     */\n    _p._$$Portrait = _k._$klass();\n    _pro = _p._$$Portrait._$extend(_i._$$Abstract);\n    /**\n     * 控件初始化\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__mopt = {\n            item:{},\n            pager:{\n                fixed:!0,\n                clazz:'zpager',\n                klass:_i0._$$SimplePager\n            },\n            onpagechange:this.__onChangePage._$bind(this)\n        };\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/portrait/portrait._$$Portrait#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = (function(){\n        var _iconf = {\n            60:{row:3,col:5,size:60},\n            30:{row:6,col:10,size:30}\n        };\n        return function(_options){\n            this.__super(_options);\n            this.__mopt.cache = _options.cache;\n            var _conf = _iconf[_options.size]||_iconf['30'];\n            this.__prefix = _options.page||'js-page-';\n            this.__mopt.limit = _conf.row*_conf.col;\n            NEJ.X(this.__mopt.item,_conf);\n            _e._$addClassName(\n                this.__nprv.parentNode,\n                'js-prev-'+_conf.size\n            );\n            this.__mdl = _t0._$$ListModulePG._$allocate(this.__mopt);\n        };\n    })();\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/portrait/portrait._$$Portrait#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        if (!!this.__mdl){\n            this.__mdl._$recycle();\n            delete this.__mdl;\n        }\n        _e._$delClassName(\n            this.__mopt.parent,\n            this.__pgcls\n        );\n        _e._$delClassName(\n            this.__nprv.parentNode,\n            'js-prev-'+this.__mopt.item.size\n        );\n        delete this.__pgcls;\n        delete this.__mopt.cache;\n    };\n    /**\n     * 初始化外观\n     *\n     * @protected\n     * @method module:ui/portrait/portrait._$$Portrait#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = (function(){\n        var _seed = _t1._$parseUITemplate(_html);\n        return function(){\n            this.__seed_css = _seed_css;\n            this.__seed_html = _seed.mid;\n            this.__mopt.item.klass = _seed.lid;\n        };\n    })();\n    /**\n     * 初始化控件节点\n     *\n     * @protected\n     * @method module:ui/portrait/portrait._$$Portrait#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        // build preview\n        this.__nprv = new Image();\n        var _node = _e._$create('div','js-prev');\n        _node.appendChild(this.__nprv);\n        // 0 - item list box\n        // 1 - pager box\n        var _list = _e._$getByClassName(this.__body,'j-flag');\n        this.__mopt.parent = _list[0];\n        this.__mopt.pager.parent = _list[1];\n        _v._$addEvent(\n            this.__mopt.parent,'click',\n            this.__onSelectPortrait._$bind(this)\n        );\n        _v._$addEvent(\n            this.__mopt.parent,'mouseover',\n            this.__onPreviewPortrait._$bind(this,!0)\n        );\n        _v._$addEvent(\n            this.__mopt.parent,'mouseout',\n            this.__onPreviewPortrait._$bind(this,!1)\n        );\n    };\n    /**\n     * 通过事件取表情数据\n     *\n     * @protected\n     * @method module:ui/portrait/portrait._$$Portrait#__getPortraitByEvent\n     * @param  {Event} arg0 -  事件对象\n     * @return {Object} 表情数据\n     */\n    _pro.__getPortraitByEvent = function(_event){\n        var _node = _v._$getElement(_event,'d:id');\n        if (!_node) return;\n        var _id = _e._$dataset(_node,'id'),\n            _data = this.__mdl._$cache()\n                        ._$getItemInCache(_id);\n        if (!_data) return;\n        return {\n            node:_node,data:_data,\n            align:_e._$dataset(_node,'align')\n        };\n    };\n    /**\n     * 解析预览图片对齐方式\n     *\n     * @protected\n     * @method module:ui/portrait/portrait._$$Portrait#__doParseAlign\n     * @param  {String} arg0 - 对齐方式，'left top'\n     * @return {Object} 对齐信息\n     */\n    _pro.__doParseAlign = function(_align){\n        var _result = {\n            top:'auto',\n            left:'auto',\n            right:'auto',\n            bottom:'auto'\n        };\n        var _arr = (_align||'').split(/\\s+/);\n        _result[_arr[0]||'left'] = 0;\n        _result[_arr[1]||'top'] = 0;\n        return _result;\n    };\n    /**\n     * 预览表情事件\n     *\n     * @protected\n     * @method module:ui/portrait/portrait._$$Portrait#__onPreviewPortrait\n     * @param  {Boolean} arg0 - 是否预览\n     * @param  {Event} arg0 -  事件对象\n     * @return {Void}\n     */\n    _pro.__onPreviewPortrait = function(_in,_event){\n        var _parent = this.__nprv.parentNode;\n        if (!_in){\n            if (this.__mopt.item.size==30){\n                _e._$setStyle(_parent,'backgroundImage','none');\n            }else{\n                this.__nprv.src = _g._$BLANK_IMAGE;\n            }\n            _e._$removeByEC(_parent);\n            return;\n        }\n        // do preview\n        var _data = this.__getPortraitByEvent(_event);\n        if (!_data) return;\n        _e._$style(_parent,this.__doParseAlign(_data.align));\n        this.__mopt.parent.appendChild(_parent);\n        var _url = _data.data.url;\n        if (this.__mopt.item.size==30){\n            _e._$setStyle(_parent,'backgroundImage','url('+_url+')');\n        }else{\n            this.__nprv.src = _url;\n        }\n    };\n    /**\n     * 选中表情触发事件\n     *\n     * @protected\n     * @method module:ui/portrait/portrait._$$Portrait#__onSelectPortrait\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onSelectPortrait = function(_event){\n        var _data = this.__getPortraitByEvent(_event);\n        if (!!_data){\n            _v._$stop(_event);\n            this._$dispatchEvent('onselect',_data.data);\n        }\n    };\n    /**\n     * 页码变化触发事件\n     *\n     * @protected\n     * @method module:ui/portrait/portrait._$$Portrait#__onChangePage\n     * @param  {Object} arg0 - 页码信息\n     * @return {Void}\n     */\n    _pro.__onChangePage = function(_event){\n        this.__pgcls = this.__prefix+(_event.index||'');\n        var _last = this.__prefix+(_event.last||'');\n        _e._$replaceClassName(\n            this.__mopt.parent,\n            _last,this.__pgcls\n        );\n    };\n    // init style and html\n    var _arr = [];\n    for(var i=0;i<6;i++){\n        for(var j=0;j<10;j++){\n            _arr.push('.'+_seed_css+' .zlst .z30-'+(i*10+j)+'{background-position:-'+(j*30)+'px -'+(i*30)+'px;}');\n        }\n    }\n    for(var i=0;i<3;i++){\n        for(var j=0;j<5;j++){\n            _arr.push('.'+_seed_css+' .zlst .z60-'+(i*5+j)+'{background-position:-'+(j*60)+'px -'+(i*60)+'px;}');\n        }\n    }\n    // ui style\n    _e._$pushCSSText(_css,{\n        uispace:_seed_css,\n        arrbg:_arr.join(' ')\n    });\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/portrait/portrait.simple.js",
    "content": "// link to ui/portrait/simple for compatible\n// use ui/portrait/simple for new project\nNEJ.define(['./simple.js'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/portrait/simple.js",
    "content": "/*\n * ------------------------------------------\n * 简易表情控件封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/portrait/simple */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/config',\n    'base/element',\n    'base/util',\n    'ui/base',\n    'ui/portrait/portrait'\n],function(NEJ,_k,_c,_e,_u,_i,_i0,_p,_o,_f,_r){\n    // variable declaration\n    var _pro,\n        _seed_css;\n    /**\n     * 简易表情控件\n     *\n     * @class   module:ui/portrait/simple._$$SimplePortrait\n     * @extends module:ui/base._$$Abstract\n     * @uses    module:ui/portrait/portrait._$$Portrait\n     * @param   {Object} 可选配置参数\n     */\n    /**\n     * 表情选中事件\n     *\n     * @event     module:ui/portrait/simple._$$SimplePortrait#onselect\n     * @param     {Object} 表情数据对象\n     * @property  {String} text  表情描述\n     * @property  {String} url   表情文件地址\n     */\n    _p._$$SimplePortrait = _k._$klass();\n    _pro = _p._$$SimplePortrait._$extend(_i._$$Abstract);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:ui/portrait/simple._$$SimplePortrait#__init\n     * @return {Void}\n     */\n    _pro.__init = (function(){\n        var _ilist = [\n            '微笑','开怀笑','哭泣','失望','困了','好好笑','啵','电到了','汗','流口水了',\n            '真困啊','我吐','眨眼','？？？','嘘','砸死你','不说','坏','色迷迷','教训',\n            '可爱','YEAH','崩溃','惊讶','鄙视','开心','仰慕你','晕','挖鼻孔','撒娇',\n            '鼓掌','害羞','老大','欠揍','吐舌笑脸','飞吻','工作忙','大哭','偷偷笑','送花给你',\n            '来，亲一个','拍桌子','拜拜','得意的笑','生气','怕怕','尴尬','难过','叹气','我是女生',\n            '玫瑰','好爱你','心碎了','亲亲','NO','YES','握个手','到点了','音乐','我是男生',\n            '带血的刀','炸弹','有了','好晚了','吸血蝙蝠','便便','干一杯','抽烟','打电话','家',\n            '车子','礼物','金钱','太阳','下雨','猪猪','小猫','小狗','骨头','喝水',\n            '汉堡','包子','西瓜','约会','CALL我'\n        ];\n        var _doInit = function(){\n            if (!!_ilist[0].id) return;\n            // push css text\n            var _arr = [],\n                _prefix = _c._$get('portrait')+'face/face-';\n            for(var i=0;i<2;i++){\n                _arr.push('.#<uispace> .js-page-'+(i+1)+' .zitm{background-image:url('+_prefix+i+'.png);}');\n            }\n            _seed_css = _e._$pushCSSText(_arr.join(' '));\n            // format data\n            var _root = _c._$get('portrait')+'face/preview/';\n            _u._$forEach(\n                _ilist,function(_text,_index,_list){\n                    _list[_index] = {\n                        text:_text,\n                        id:'sp-'+_index,\n                        url:_root+'face'+_index+'.gif'\n                    };\n                }\n            );\n        };\n        return function(){\n            _doInit();\n            this.__popt = {\n                cache:{\n                    list:_ilist,\n                    lkey:'portrait',\n                    id:'nej-simple-portrait'\n                }\n            };\n            this.__super();\n        };\n    })();\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/portrait/simple._$$SimplePortrait#__reset\n     * @param  {Object} 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        _options.cache = _u._$merge({},this.__popt.cache);\n        _options.clazz = _seed_css+' '+(_options.clazz||'');\n        this.__portrait = _i0._$$Portrait._$allocate(_options);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/portrait/simple._$$SimplePortrait#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        if (!!this.__portrait){\n            this.__portrait._$recycle();\n            delete this.__portrait;\n        }\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/range/range.css",
    "content": ".#<uispace>{position:absolute;top:0;left:0;width:0;height:0;overflow:hidden;border:1px solid #0C32F6;background:#B8D4F0;_filter:alpha(opacity=70);opacity:0.7;}"
  },
  {
    "path": "src/ui/range/range.js",
    "content": "/*\n * ------------------------------------------\n * 范围选择控件封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/range/range */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'ui/base',\n    'util/range/range',\n    'text!./range.css'\n],function(NEJ,_k,_e,_i,_t0,_css,_p,_o,_f,_r){\n    var _pro,\n        _seed_css = _e._$pushCSSText(_css);\n    /**\n     * 范围选择控件封装\n     *\n     * @class   module:ui/range/range._$$Range\n     * @extends module:ui/base._$$Abstract\n     * @param   {Object} arg0 - 可选配置参数\n     */\n    /**\n     * 页码切换事件\n     *\n     * @event  module:ui/range/range._$$Range#onchange\n     * @param  {Object} arg0 -   区域信息\n     */\n    /**\n     * 区域变化之后触发事件\n     *\n     * @event  module:ui/range/range._$$Range#onafterchange\n     */\n    /**\n     * 区域变化之前触发事件\n     *\n     * @event  module:ui/range/range._$$Range#onbeforechange\n     * @param  {Object} arg0 -   区域信息\n     */\n    _p._$$Range = _k._$klass();\n    _pro = _p._$$Range._$extend(_i._$$Abstract);\n    /**\n     * 初始化控件\n     *\n     * @protected\n     * @method module:ui/range/range._$$Range#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__ropt = {\n            onchange:this.__onRangeChange._$bind(this)\n           ,onafterchange:this.__onAfterRangeChange._$bind(this)\n           ,onbeforechange:this.__onBeforeRangeChange._$bind(this)\n        };\n        this.__super();\n    };\n    /**\n     * 重置控件\n     *\n     * @protected\n     * @method module:ui/range/range._$$Range#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__ropt.parent = this.__parent;\n        this.__range = _t0._$$Range._$allocate(this.__ropt);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/range/range._$$Range#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        this.__range._$recycle();\n        delete this.__range;\n        delete this.__ropt.parent;\n    };\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/range/range._$$Range#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css = _seed_css;\n    };\n    /**\n     * 初始化结构\n     *\n     * @protected\n     * @method module:ui/range/range._$$Range#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        this.__body.innerHTML = '&nbsp;';\n        this.__ropt.body = this.__body;\n    };\n    /**\n     * 区域变化触发事件\n     *\n     * @protected\n     * @method module:ui/range/range._$$Range#__onRangeChange\n     * @param  {Object} arg0 - 区域信息\n     * @return {Void}\n     */\n    _pro.__onRangeChange = function(_event){\n        this._$dispatchEvent('onchange',_event);\n    };\n    /**\n     * 区域变化触发事件\n     *\n     * @protected\n     * @method module:ui/range/range._$$Range#__onBeforeRangeChange\n     * @param  {Object} arg0 - 区域信息\n     * @return {Void}\n     */\n    _pro.__onBeforeRangeChange = function(_event){\n        this._$dispatchEvent('onbeforchange',_event);\n    };\n    /**\n     * 区域变化触发事件\n     *\n     * @protected\n     * @method module:ui/range/range._$$Range#__onAfterRangeChange\n     * @param  {Object} arg0 - 区域信息\n     * @return {Void}\n     */\n    _pro.__onAfterRangeChange = function(){\n        this._$dispatchEvent('onafterchange');\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/resizer/demo/resizer.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>resizer demo</title>\n    <meta charset=\"utf-8\" />\n    <style>\n        body,html{width:100%;height:100%;}\n    </style>\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n  </head>\n  <body>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n      NEJ.define([\n          '../resizer.js'\n      ],function(_i){\n          _i._$$Resizer._$allocate({\n              parent:document.body\n          });\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/ui/resizer/resizer.css",
    "content": ".#<uispace>-parent{position:relative;}\n.#<uispace>{position:absolute;top:0;left:0;border:1px solid #aaa;cursor:move;$<user-select>:none;z-index:1000;}\n.#<uispace> .zln{width:48px;height:48px;border:1px solid #fff;background:url(#<blankimage>);}\n.#<uispace> .zpc{border:1px solid #aaa;}\n.#<uispace> .zpt{position:absolute;width:5px;height:5px;font-size:1px;overflow:hidden;}\n.#<uispace> .znt{top:-1px;left:-1px;width:100%;cursor:n-resize;}\n.#<uispace> .znr{top:-1px;right:-1px;height:100%;cursor:e-resize;}\n.#<uispace> .znb{bottom:-1px;left:-1px;width:100%;cursor:s-resize;}\n.#<uispace> .znl{top:-1px;left:-1px;height:100%;cursor:w-resize;}\n.#<uispace> .zntl{top:-1px;left:-1px;cursor:nw-resize;}\n.#<uispace> .zntr{top:-1px;right:-1px;cursor:ne-resize;}\n.#<uispace> .znbr{bottom:-1px;right:-1px;cursor:se-resize;}\n.#<uispace> .znbl{bottom:-1px;left:-1px;cursor:sw-resize;}"
  },
  {
    "path": "src/ui/resizer/resizer.html",
    "content": "<div>\n  <div class=\"zln\">\n  {list clazz as x}\n    <div class=\"zpt ${x} js-rs-${x_index+1}\">&nbsp;</div>\n  {/list}\n  </div>\n</div>\n"
  },
  {
    "path": "src/ui/resizer/resizer.js",
    "content": "/*\n * ------------------------------------------\n * 范围裁剪控件封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/resizer/resizer */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/constant',\n    'base/element',\n    'base/util',\n    'ui/base',\n    'util/resize/resize',\n    'util/template/tpl',\n    'util/template/jst',\n    'text!./resizer.css',\n    'text!./resizer.html'\n],function(NEJ,_k,_g,_e,_u,_i,_t0,_t1,_t2,_css,_html,_p,_o,_f,_r){\n    var _pro,\n        _seed_html,\n        _seed_point = _t2._$add(_html);\n    /**\n     * 初始大小\n     * @typedef  {Object} module:ui/resizer/resizer._$$Resizer~Size\n     * @property {Number} width  - 宽\n     * @property {Number} height - 高\n     * @property {Number} ratio  - 比例\n     */\n    /**\n     * 最大宽高限制\n     * @typedef  {Object} module:ui/resizer/resizer._$$Resizer~Max\n     * @property {Number} width  - 宽\n     * @property {Number} height - 高\n     */\n    /**\n     * 范围裁剪控件封装\n     *\n     * @class     module:ui/resizer/resizer._$$Resizer\n     * @extends   module:ui/base._$$Abstract\n     * @param     {Object} arg0 - 可选配置参数，其他参数见module:util/resize/resize._$$ResizerResize控件所示\n     * @property  {module:ui/resizer/resizer._$$Resizer~Size} size - 初始大小，输入任意两个值，其中ratio为width/height\n     * @property  {module:ui/resizer/resizer._$$Resizer~Max}  max  - 最大宽高限制\n     */\n    _p._$$Resizer = _k._$klass();\n    _pro = _p._$$Resizer._$extend(_i._$$Abstract);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:ui/resizer/resizer._$$Resizer#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__ropt = {\n            onbeforeresize:this.__onBeforeResize._$bind(this),\n            onresizestart:this._$dispatchEvent._$bind(this,'onresizestart'),\n            onresizeend:this._$dispatchEvent._$bind(this,'onresizeend'),\n            onresize:this._$dispatchEvent._$bind(this,'onresize'),\n            onmove:this._$dispatchEvent._$bind(this,'onmove')\n        };\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/resizer/resizer._$$Resizer#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = (function(){\n        var _doParseSize = function(_size,_max){\n            if (!_size) return;\n            var _result,\n                _width = _size.width,\n                _height = _size.height,\n                _ratio = _size.ratio;\n            if (!!_width&&!!_height){\n                _result = {\n                    width:_width-2,\n                    height:_height-2\n                };\n            }else if(!!_ratio){\n                if (!!_width){\n                    _result = {\n                        width:_width-2,\n                        height:Math.floor(_width/_ratio)-2\n                    };\n                }else if(!!_height){\n                    _result = {\n                        height:_height-2,\n                        width:Math.floor(_height*_ratio)-2\n                    };\n                }\n            }\n            // fix max limit\n            if (!!_max){\n                var _maxw = _max.width-2,\n                    _maxh = _max.height-2,\n                    _orgw = _result.width,\n                    _orgh = _result.height,\n                    _delta = _maxw/_maxh-_orgw/_orgh;\n                if (_delta>0&&_orgh>_maxh){\n                    _result.height = _maxh;\n                    _result.width = Math.floor(_orgw*_maxh/_orgh);\n                }else if(_delta<0&&_orgw>_maxw){\n                    _result.width = _maxw;\n                    _result.height = Math.floor(_maxw*_orgh/_orgw);\n                }\n            }\n            _result.width += 'px';\n            _result.height += 'px';\n            return _result;\n        };\n        return function(_options){\n            this.__super(_options);\n            var _opt = _u._$merge(_u._$fetch({\n                lock:!1,\n                min:null\n            },_options),this.__ropt);\n            _opt.view = this.__parent;\n            _opt.body = this.__body;\n            _e._$style(\n                this.__nsize,\n                _doParseSize(_options.size,_options.max)\n            );\n            this.__resize = _t0._$$Resize._$allocate(_opt);\n        };\n    })();\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/resizer/resizer._$$Resizer#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        if (!!this.__resize){\n            this.__resize._$recycle();\n            delete this.__resize;\n        }\n        this.__super();\n    };\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/resizer/resizer._$$Resizer#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = (function(){\n        var _seed_css   = _e._$pushCSSText(\n            _css,{blankimage:_g._$BLANK_IMAGE}\n        );\n        return function(){\n            this.__seed_css = _seed_css;\n            this.__seed_html = _seed_html;\n        };\n    })();\n    /**\n     * 动态构建控件节点模板\n     *\n     * @protected\n     * @method module:ui/resizer/resizer._$$Resizer#__initNodeTemplate\n     * @return {Void}\n     */\n    _pro.__initNodeTemplate = (function(){\n        var _clazz = [\n            'znt','znr','znb','znl',\n            'zpc zntl','zpc zntr','zpc znbr','zpc znbl'\n        ];\n        return function(){\n            _seed_html = _t1._$addNodeTemplate(\n                _t2._$get(_seed_point,{clazz:_clazz})\n            );\n            this.__seed_html = _seed_html;\n        };\n    })();\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method module:ui/resizer/resizer._$$Resizer#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        this.__nsize = _e._$getChildren(this.__body)[0];\n        this.__ropt.sbody = this.__nsize;\n    };\n    /**\n     * 大小变化之前触发事件\n     *\n     * @protected\n     * @method module:ui/resizer/resizer._$$Resizer#__onBeforeResize\n     * @return {Void}\n     */\n    _pro.__onBeforeResize = function(_event){\n        _event.stopped = !0;\n        _e._$style(\n            this.__nsize,{\n                width:_event.width+'px',\n                height:_event.height+'px'\n            }\n        );\n        _e._$style(\n            this.__body,{\n                top:_event.top+'px',\n                left:_event.left+'px'\n            }\n        );\n        this._$dispatchEvent('onresize',this._$getResizeBox());\n    };\n    /**\n     * 裁剪信息\n     *\n     * @typedef  {Object} module:ui/resizer/resizer._$$Resizer~ResizeBox\n     * @property {Number} top    - 距离上\n     * @property {Number} left   - 距离左\n     * @property {Number} width  - 宽\n     * @property {Number} height - 高\n     */\n    /**\n     * 取裁剪信息\n     *\n     * @method module:ui/resizer/resizer._$$Resizer#_$getResizeBox\n     * @return {module:ui/resizer/resizer._$$Resizer~ResizeBox} 信息\n     */\n    _pro._$getResizeBox = function(){\n        return this.__resize._$getResizeBox();\n    };\n    /**\n     * 更新裁剪信息\n     * \n     * @method module:ui/resizer/resizer._$$Resizer#_$update\n     * @param  {module:ui/resizer/resizer._$$Resizer~ResizeBox} arg0 - 裁剪信息\n     * @return {Void}\n     */\n    _pro._$update = function(_box){\n        this.__resize._$update(_box);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/scroller/demo/y.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test scroll y</title>\n    <meta charset=\"utf-8\"/>\n    <style>\n      .abc{position:relative;}\n      .abc p{margin:50px 0;}\n    </style>\n  </head>\n  <body>\n    <div class=\"abc\" id=\"abc\">\n      <p>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</p>\n      <p>bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb</p>\n      <p>cccccccccccccccccccccccccccccccccc</p>\n      <p>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</p>\n      <p>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</p>\n      <p>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</p>\n      <p>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</p>\n    </div>\n    <script src=\"../../../../src/define.js\"></script>\n    <script>\n      define([\n          '../y.js'\n      ],function(_i){\n          _i._$$ScrollerY._$allocate({\n              container:'abc'\n          });\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/ui/scroller/list.css",
    "content": ".#<uispace>{position:relative;}"
  },
  {
    "path": "src/ui/scroller/list.js",
    "content": "/*\n * ------------------------------------------\n * 列表滚动控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/scroller/list */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/util',\n    'ui/base',\n    'ui/scroller/scroller.y',\n    'ui/pullrefresh/puller',\n    'text!./list.css'\n],function(NEJ,_k,_e,_u,_i,_i0,_i1,_css,_p,_o,_f,_r){\n    // variable declaration\n    var _pro,\n        _seed_css = _e._$pushCSSText(_css);\n    /**\n     * 列表滚动控件\n     *\n     * @class     module:ui/scroller/list._$$ListScroller\n     * @extends   module:ui/base._$$Abstract\n     * @param     {Object} arg0   - 可选配置参数\n     * @property  {module:ui/scroller/y._$$ScrollerY.Config} config - 滚动参数配置信息\n     */\n    /**\n     * 列表滚动触发事件\n     *\n     * @event  module:ui/scroller/list._$$ListScroller#onscroll 列表滚动触发事件\n     * @param  {Number} offset - 当前位置\n     */\n    /**\n     * 弹性触发事件\n     *\n     * @event    module:ui/scroller/list._$$ListScroller#onbounce\n     * @param    {Object} arg0      - 弹性信息\n     * @property {Number} movement  - 偏移量\n     * @property {Number} direction - 方向\n     * |       数值 |  含义                     |\n     * |       :--- |  :---                     |\n     * |       <0   |  正向滚动(远离顶部的滚动) |\n     * |       >0   |  反向滚动(接近顶部的滚动) |\n     */\n    /**\n     * 弹性开始时触发事件\n     *\n     * @event  module:ui/scroller/list._$$ListScroller#onbouncestart\n     */\n    /**\n     * 列表更新触发事件\n     *\n     * @event  module:ui/scroller/list._$$ListScroller#onlistupdate\n     * @param  {Node} arg0 - 更新后的节点\n     */\n    /**\n     * 列表清除之前触发事件\n     *\n     * @event  module:ui/scroller/list._$$ListScroller#onbeforeclear\n     * @param  {Node} arg0 - 缓存的节点\n     */\n    _p._$$ListScroller = _k._$klass();\n    _pro = _p._$$ListScroller._$extend(_i._$$Abstract);\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/scroller/list._$$ListScroller#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css = _seed_css;\n    };\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method module:ui/scroller/list._$$ListScroller#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        this.__cache = {};\n        this.__nlist = e._$create('div','z-list');\n        this.__sopt  = {container:this.__body,style:'z-bar',\n                        onscroll:this.__onScrolling._$bind(this),\n                        onbounce:this.__onScrollBounce._$bind(this),\n                        onrelease:this.__onScrollRelease._$bind(this),\n                        onbouncestart:this._$dispatchEvent._$bind(this,'onbouncestart')};\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method   module:ui/scroller/list._$$ListScroller#__reset\n     * @param    {Object} arg0 - 可选配置参数\n     * @property {module:ui/scroller/y._$$ScrollerY.Config} config - 滚动参数配置信息\n     * @return   {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__body.appendChild(this.__nlist);\n        this.__sopt.parent = this.__parent;\n        this.__sopt.config = _options.config;\n        this.__scroller = p._$$ScrollerY._$allocate(this.__sopt);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/scroller/list._$$ListScroller#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this._$setList();\n        e._$removeByEC(this.__nlist);\n        this.__super();\n        if (!!this.__puller)\n            this.__puller = this.__puller.constructor\n                                ._$recycle(this.__puller);\n        this.__scroller = p._$$ScrollerY._$recycle(this.__scroller);\n    };\n    /**\n     * 内容封装\n     *\n     * @protected\n     * @method module:ui/scroller/list._$$ListScroller#__doParseWrapBox\n     * @param  {String} arg0 - 内容\n     * @return {Node}   封装后的内容节点\n     */\n    _pro.__doParseWrapBox = function(_html){\n        if (!_html) return null;\n        var _node = e._$create('div','z-box');\n        _node.id = 'box-' + _u._$uniqueID();\n        _node.innerHTML = _html;\n        return _node;\n    };\n    /**\n     * 列表清理\n     *\n     * @protected\n     * @method module:ui/scroller/list._$$ListScroller#__doPerformListClear\n     * @return {Void}\n     */\n    _pro.__doPerformListClear = function(){\n        var _list = e._$getChildren(this.__nlist);\n        if (!_list||!_list.length) return;\n        for(var i=0,l=_list.length,_id,_box;i<l;i++){\n            _box = _list[i]; _id = _box.id;\n            _box = this.__cache[_id]||_box;\n            delete this.__cache[_id];\n            this._$dispatchEvent('onbeforeclear',_box);\n        }\n    };\n    /**\n     * 图片延时载入优化\n     *\n     * @protected\n     * @method module:ui/scroller/list._$$ListScroller#__doPerformImage\n     * @param  {Node} arg0 -    容器节点\n     * @return {Boolean} 是否存在未处理的图片\n     */\n    _pro.__doPerformImage = function(_node){\n        if (!!_node.finished) return;\n        var _ndpf = !1,\n            _images = _node.getElementsByTagName('img');\n        if (!!_images&&!!_images.length)\n            for(var i=0,l=_images.length,_image,_src;i<l;i++){\n                _image = _images[i];\n                _src   = e._$dataset(_image,'src');\n                if (!_src) continue;\n                if (!this.__scroller._$isInViewPoint(_image)){\n                    _ndpf = !0; continue;\n                }\n                _image.src = _src;\n                e._$dataset(_image,'src','');\n            }\n        if (!_ndpf) _node.finished = !0;\n    };\n    /**\n     * 优化节点的显示\n     *\n     * @protected\n     * @method module:ui/scroller/list._$$ListScroller#__doPerformNode\n     * @param  {Node} arg0 - 节点\n     * @return {Void}\n     */\n    _pro.__doPerformNode = function(_node){\n        this.__scroller._$isInViewPoint(_node)\n        ? this.__doPerformAppend(_node.id)\n        : this.__doPerformRecycle(_node.id);\n    };\n    /**\n     * 执行节点追加\n     *\n     * @protected\n     * @method module:ui/scroller/list._$$ListScroller#__doPerformAppend\n     * @param  {String} arg0 - 节点ID\n     * @return {Void}\n     */\n    _pro.__doPerformAppend = function(_id){\n        var _parent = e._$get(_id),\n            _children = this.__cache[_id];\n        if (!!_parent&&!!_children){\n            _parent.appendChild(_children);\n            _parent.style.height = 'auto';\n        }\n        delete this.__cache[_id];\n        this.__doPerformImage(_parent);\n    };\n    /**\n     * 执行节点回收\n     *\n     * @protected\n     * @method module:ui/scroller/list._$$ListScroller#__doPerformRecycle\n     * @param  {String} arg0 - 节点ID\n     * @return {Void}\n     */\n    _pro.__doPerformRecycle = function(_id){\n        var _parent = e._$get(_id);\n        if (!_parent||!!this.__cache[_id]) return;\n        var _fragment = document.createDocumentFragment();\n        this.__cache[_id] = _fragment;\n        _parent.style.height = _parent.scrollHeight+'px';\n        var _children = e._$getChildren(_parent);\n        if (!_children||!_children.length) return;\n        var _element = _children.shift();\n        while(!!_element){\n            _fragment.appendChild(_element);\n            _element = _children.shift();\n        }\n    };\n    /**\n     * 优化滚动\n     *\n     * @protected\n     * @method module:ui/scroller/list._$$ListScroller#__doPerformWithTimer\n     * @return {Void}\n     */\n    _pro.__doPerformWithTimer = function(){\n        var _list = e._$getChildren(this.__nlist);\n        if (!_list||!_list.length) return;\n        this.__doPerformImage(_list[0]);\n        for(var i=1,l=_list.length,_id,_tmp0;i<l;i++){\n            _id = _list[i].id;\n            _tmp0 = this.__scroller._$isInViewPoint(_list[i]);\n            _tmp0 ? this.__doPerformAppend(_id)\n                  : this.__doPerformRecycle(_id);\n        }\n    };\n    /**\n     * 滚动事件\n     *\n     * @protected\n     * @method module:ui/scroller/list._$$ListScroller#__onScrolling\n     * @param  {Number} arg0 - 当前位置\n     * @return {Void}\n     */\n    _pro.__onScrolling = (function(){\n        var _timer = null;\n        return function(_offset){\n            if (!_timer)\n                _timer = window.setTimeout(function(){\n                    _timer = window.clearTimeout(_timer);\n                    this.__performed ? this.__doPerformWithTimer()\n                                     : this.__doPerformImage(this.__nlist);\n                }._$bind(this),150);\n            this._$dispatchEvent('onscroll',_offset);\n        };\n    })();\n    /**\n     * 滚动结束\n     *\n     * @protected\n     * @method module:ui/scroller/list._$$ListScroller#__onScrollRelease\n     * @return {Void}\n     */\n    _pro.__onScrollRelease = function(_event){\n        if (!this.__puller||\n             this.__puller._$getState()!=1) return;\n        // auto revert bounce to state bar\n        _event.offset = this.__puller._$getRange();\n        this.__puller._$setState(2);\n        window.setTimeout(function(){\n            this.__puller._$dispatchEvent('onrefresh');\n        }._$bind(this),250);\n    };\n    /**\n     * 滚动弹性\n     *\n     * @protected\n     * @method module:ui/scroller/list._$$ListScroller#__onScrollBounce\n     * @param  {Object} arg0 - 弹性信息\n     * @return {Void}\n     */\n    _pro.__onScrollBounce = function(_event){\n        var _distance = _event.movement||0;\n        if (!!this.__puller&&_distance>0&&\n            this.__puller._$getState()!=2)\n            this.__puller._$setState(this.__puller\n                         ._$isOutThreshold(_distance)?1:0);\n        this._$dispatchEvent('onbounce',_event);\n    };\n    /**\n     * 执行性能优化\n     *\n     * @method module:ui/scroller/list._$$ListScroller#_$performance\n     * @return {Void}\n     */\n    _pro._$performance = function(){\n        this.__performed = !0;\n    };\n    /**\n     * 绑定下拉更新控件\n     *\n     * @method module:ui/scroller/list._$$ListScroller#_$bindPuller\n     * @param  {nej.ui._$$Puller} arg0 - 下拉更新控件\n     * @return {Void}\n     */\n    _pro._$bindPuller = function(_puller){\n        if (!(_puller instanceof p._$$Puller)) return;\n        if (!!this.__puller){\n            _puller._$setState(this.__puller._$getState());\n            this.__puller.constructor._$recycle(this.__puller);\n        }\n        this.__puller = _puller;\n        this.__body.insertAdjacentElement(\n            'afterBegin',this.__puller._$getBody());\n    };\n    /**\n     * 追加更多列表\n     *\n     * @method module:ui/scroller/list._$$ListScroller#_$addMore\n     * @param  {String} arg0 - 列表html代码\n     * @return {Void}\n     */\n    _pro._$addMore = function(_html){\n        var _node = this.__doParseWrapBox(_html);\n        if (!!_node){\n            this.__nlist.appendChild(_node);\n            this.__doPerformImage(_node);\n            this._$dispatchEvent('onlistupdate',_node);\n        }\n    };\n    /**\n     * 追加最新列表\n     * @method module:ui/scroller/list._$$ListScroller#_$addLast\n     * @param  {String} arg0 - 列表html代码\n     * @return {Void}\n     */\n    _pro._$addLast = function(_html){\n        this.__scroller._$revertBounce();\n        window.setTimeout(function(){\n            this.__puller._$setState(3);\n            var _node = this.__doParseWrapBox(_html);\n            if (!!_node){\n                this.__nlist.insertAdjacentElement('afterBegin',_node);\n                this.__doPerformImage(_node);\n                this._$dispatchEvent('onlistupdate',_node);\n            }\n        }._$bind(this),250);\n    };\n    /**\n     * 设置列表\n     *\n     * @method module:ui/scroller/list._$$ListScroller#_$setList\n     * @param  {String} arg0 - 列表html代码\n     * @return {Void}\n     */\n    _pro._$setList = function(_html){\n        this.__doPerformListClear();\n        this.__nlist.innerHTML = '';\n        this._$addMore(_html);\n        this._$scrollTop();\n    };\n    /**\n     * 判断偏移是否在可视范围内\n     *\n     * @method module:ui/scroller/list._$$ListScroller#_$isInViewPoint\n     * @param  {String|Node} arg0 - 检测节点\n     * @return {Boolean}     是否在可视范围内\n     */\n    _pro._$isInViewPoint = function(_element){\n        return this.__scroller._$isInViewPoint.apply(this.__scroller,arguments);\n    };\n    /**\n     * 取当前滚动高度\n     *\n     * @method module:ui/scroller/list._$$ListScroller#_$getScrollTop\n     * @return {Number} 滚动高度\n     */\n    _pro._$getScrollTop = function(){\n        return this.__scroller._$getScrollTop.apply(this.__scroller,arguments);\n    };\n    /**\n     * 滚动至偏移位置\n     *\n     * @method module:ui/scroller/list._$$ListScroller#_$scrollBy\n     * @param  {Number}  delta   - 偏移量\n     * @param  {Boolean} refresh - 是否需要刷新\n     * @return {Void}\n     */\n    _pro._$scrollBy = function(_delta,_refresh){\n        this.__scroller._$scrollBy.apply(this.__scroller,arguments);\n    };\n    /**\n     * 滚动至指定位置\n     *\n     * @method module:ui/scroller/list._$$ListScroller#_$scrollTo\n     * @param  {Number}  delta   - 偏移量\n     * @param  {Boolean} refresh - 是否需要刷新\n     * @return {Void}\n     */\n    _pro._$scrollTo = function(_offset,_refresh){\n        this.__scroller._$scrollTo.apply(this.__scroller,arguments);\n    };\n    /**\n     * 滚动至顶部\n     *\n     * @method module:ui/scroller/list._$$ListScroller#_$scrollTop\n     * @param  {Boolean} arg0 - 是否需要刷新\n     * @return {Void}\n     */\n    _pro._$scrollTop = function(_refresh){\n        this.__scroller._$scrollTop.apply(this.__scroller,arguments);\n    };\n    /**\n     * 滚动至中部\n     *\n     * @method module:ui/scroller/list._$$ListScroller#_$scrollMiddle\n     * @param  {Boolean} arg0 - 是否需要刷新\n     * @return {Void}\n     */\n    _pro._$scrollMiddle = function(_refresh){\n        this.__scroller._$scrollMiddle.apply(this.__scroller,arguments);\n    };\n    /**\n     * 滚动至底部\n     *\n     * @method module:ui/scroller/list._$$ListScroller#_$scrollBottom\n     * @param  {Boolean} arg0 - 是否需要刷新\n     * @return {Void}\n     */\n    _pro._$scrollBottom = function(_refresh){\n        this.__scroller._$scrollBottom.apply(this.__scroller,arguments);\n    };\n    /**\n     * 滚动到指定元素\n     *\n     * @method module:ui/scroller/list._$$ListScroller#_$scrollToElement\n     * @param  {String|Node} element - 目标元素\n     * @param  {Boolean}     refresh - 是否需要刷新\n     * @return {Void}\n     */\n    _pro._$scrollToElement = function(_element,_refresh){\n        this.__scroller._$scrollToElement.apply(this.__scroller,arguments);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/scroller/scroller.js",
    "content": "﻿/**\n * ------------------------------------------\n * 滚动控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/scroller/scroller */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'base/util',\n    'ui/base',\n    'util/gesture/tap',\n    'util/gesture/drag',\n    'util/animation/bounce',\n    'util/animation/easeout',\n    'util/animation/decelerate'\n],function(NEJ,_k,_e,_v,_u,_i,_t0,_t1,_t2,_t3,_t4,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 滚动配置信息\n     * @typedef  {Object}      module:ui/scroller/scroller._$$Scroller~Config\n     * @property {Float}       bcfactor - 弹性移动距离与触点移动距离比例，默认0.5 表示触点移动2px弹性增加1px\n     * @property {Float}       minbar - 滚动条保留的最小高度与窗体可视高度比例，默认1/3\n     * @property {Number}      reset  - 滚动加速检测时间间隔【单位ms】，默认350，连续滚动操作350ms后重新开始计算加速初始速度\n     * @property {Number}      acceleration - 减速度，值越大加速越慢，默认30\n     * @property {Number}      minvelocity  - 加速最小初始速度，默认为1\n     * @property {String|Node} container    - 内容容器节点ID或者对象\n     */\n    /**\n     * 滚动控件\n     * @class    module:ui/scroller/scroller._$$Scroller\n     * @extends  module:ui/base._$$Abstract\n     * @param    {Object} options - 可选配置参数\n     * @property {module:ui/scroller/scroller._$$Scroller~Config} config  - 滚动配置信息\n     */\n    /**\n     * 滚动过程触发事件\n     *\n     * @event module:ui/scroller/scroller._$$Scroller#onscroll\n     */\n    /**\n     * 滚动动画结束触发事件（不包括弹性）\n     *\n     * @event module:ui/scroller/scroller._$$Scroller#onscrollend\n     */\n    /**\n     * 弹性效果过程触发事件\n     *\n     * @event module:ui/scroller/scroller._$$Scroller#onbounce\n     */\n    /**\n     * 弹性结束触发事件\n     *\n     * @event module:ui/scroller/scroller._$$Scroller#onbouncend\n     */\n    /**\n     * 弹性开始触发事件\n     *\n     * @event module:ui/scroller/scroller._$$Scroller#onbouncestart\n     */\n    /**\n     * 释放滚动触发事件\n     *\n     * @event module:ui/scroller/scroller._$$Scroller#onrelease\n     */\n    _p._$$Scroller = _k._$klass();\n    _pro = _p._$$Scroller._$extend(_i._$$Abstract);\n    /**\n     * 初始化控件\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__super();\n        this.__momentum = {};\n        this.__config = this.__getConfig();\n        this.__alopt = {from:{},to:{},\n                        onstop:this.__doStopBounceRevert._$bind(this),\n                        onupdate:this.__doUpdateBounceRevert._$bind(this)};\n        this.__adopt = {from:{},\n                        onstop:this.__doStopDecelerate._$bind(this),\n                        onupdate:this.__doUpdateDecelerate._$bind(this)};\n        this.__abopt = {from:{},\n                        onstop:this.__doStopBounce._$bind(this),\n                        onupdate:this.__doUpdateBounce._$bind(this)};\n        this.__evopt = {ontapstart:this.__onTouchStart._$bind(this),\n                        ondragstart:this.__onDragStart._$bind(this),\n                        ondrag:this.__onDragging._$bind(this),\n                        ondragend:this.__onDragEnd._$bind(this),\n                        ontransitionend:this.__onTransitionEnd._$bind(this)};\n    };\n    /**\n     * 取滚动配置信息，子类实现具体逻辑\n     *\n     * @abstract\n     * @return {Object} 滚动配置信息\n     */\n    _pro.__getConfig = _f;\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__reset\n     * @param  {Object} _options - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__doInitDomEvent([\n            [this.__parent.parentNode,'touchstart',v._$stopDefault],\n            [this.__parent.parentNode,'touchmove',v._$stopDefault]\n        ]);\n        // init param\n        this.__bpoint = [0,0];\n        this.__animate = {minvelocity:1,\n                          bcfactor:0.5,minbar:1/5,\n                          reset:300,acceleration:30};\n        _u._$fetch(this.__animate,_options.config);\n        this.__cbox = _e._$get(_options.container)||\n                      _e._$getChildren(this.__parent)[0];\n        _e._$addClassName(this.__cbox,this.__seed+'-view');\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        _e._$delClassName(this.__cbox,this.__seed+'-view');\n        delete this.__offset;\n        _e._$setStyle(this.__cbox,'transform','');\n    };\n    /**\n     * 刷新滚动控件参数\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__refresh\n     * @return {Void}\n     */\n    _pro.__refresh = (function(){\n        var _offset = function(_element,_attr){\n            if (!_element) return 0;\n            var _value = _element[_attr];\n            while(!!_element&&!_value){\n                _element = _element.parentNode;\n                if (!!_element)\n                    _value = _element[_attr];\n            }\n            return _value;\n        };\n        return function(){\n            var _sbox = this.__cbox[this.__config.sb],\n                _obox = _offset(this.__parent,this.__config.ob);\n            this.__scrollable = _sbox>_obox;\n            this.__boxsize = _obox;\n            this.__barsize = Math.max(_obox*_obox/_sbox,\n                                      _obox*this.__animate.minbar);\n            this.__scratio = (_obox-this.__barsize)/(_sbox-_obox);\n            this.__body.style[this.__config.g] = this.__barsize+'px';\n            this.__bpoint = [Math.min(0,_obox-_sbox),0];\n            this.__offset = this.__getOffset();\n        };\n    })();\n    /**\n     * 清理定时器\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__clearScrollBarTimer\n     * @return {Void}\n     */\n    _pro.__clearScrollBarTimer = function(){\n        if (!this.__timer) return;\n        this.__timer = window.clearTimeout(this.__timer);\n    };\n    /**\n     * 显示滚动条\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__showScrollBar\n     * @return {Void}\n     */\n    _pro.__showScrollBar = function(){\n        if (!this.__barable||\n            !this.__scrollable) return;\n        this.__clearScrollBarTimer();\n        this.__body.style.opacity = 1;\n    };\n    /**\n     * 隐藏滚动条\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__hideScrollBar\n     * @return {Void}\n     */\n    _pro.__hideScrollBar = function(){\n        if (!this.__barable||\n            !this.__scrollable) return;\n        this.__clearScrollBarTimer();\n        // delay 0.5s hide scrollbar\n        this.__timer = window.setTimeout(function(){\n            this.__body.style.opacity = 0;\n        }._$bind(this),300);\n    };\n    /**\n     * 取偏移量\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__getOffset\n     * @return {Number} 偏移量\n     */\n    _pro.__getOffset = function(){\n        var _transform = _e._$matrix(e.\n            _$getStyle(this.__cbox,'transform'));\n        return parseInt(_transform[this.__config.dx])||0;\n    };\n    /**\n     * 取弹性距离\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__getOutofBounce\n     * @param  {Number} _offset - 偏移量\n     * @return {Number}         弹性距离\n     * |        数值         |        含义          |\n     * |        :---         |        :---          |\n     * |        <0           |        下超出        |\n     * |        =0           |        非弹性超出    |\n     * |        >0           |        上超出        |\n     */\n    _pro.__getOutofBounce = function(_offset){\n        var _out = _offset==null?this.__offset:_offset;\n        if (this.__bpoint[0]<=_out&&\n            this.__bpoint[1]>=_out)\n            return 0;\n        var _delta = _out-this.__bpoint[0];\n        if (_delta<0) return _delta;\n        _delta = _out-this.__bpoint[1];\n        if (_delta>0) return _delta;\n    };\n    /**\n     * 刷新布局信息\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__doRefresh\n     * @param  {Boolean} _force - 强制刷新\n     * @return {Void}\n     */\n    _pro.__doRefresh = function(_force){\n        _force = !!_force||this.__offset===undefined;\n        if (!!_force) this.__refresh();\n    };\n    /**\n     * 恢复弹性\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__doRevertBounce\n     * @param  {Number} _offset   - 弹性距离\n     * @param  {Number} _duration - 持续时间\n     * @return {Void}\n     */\n    _pro.__doRevertBounce = function(_offset,_duration){\n        var _distance = this.__getOutofBounce();\n        if (_distance!=0&&!this.__linear){\n            var _end = _offset!=null ? _offset\n                     : this.__bpoint[_distance<0?0:1];\n            this.__alopt.duration = _duration||200;\n            this.__alopt.from.offset = this.__offset;\n            this.__alopt.to.offset = _end;\n            this.__linear = _t3._$$AnimEaseOut._$allocate(this.__alopt);\n            this.__linear._$play();\n            return !0;\n        }\n    };\n    /**\n     * 弹性恢复动画回收\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__doStopBounceRevert\n     * @return {Void}\n     */\n    _pro.__doStopBounceRevert = function(){\n        if (!!this.__linear)\n            this.__linear = this.__linear._$recycle();\n        this.__skip = !1;\n    };\n    /**\n     * 更新弹性恢复\n     *\n     * @protected\n     * @method   module:ui/scroller/scroller._$$Scroller#__doUpdateBounceRevert\n     * @param    {Object} _event  - 偏移量对象\n     * @property {Number} offset  - 偏移量\n     * @return {Void}\n     */\n    _pro.__doUpdateBounceRevert = function(_event){\n        this.__doScrollTo(_event.offset);\n    };\n    /**\n     * 减速动画回收\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__doStopDecelerate\n     * @param  {Boolean} _nohide  - 是否回收\n     * @return {Void}\n     */\n    _pro.__doStopDecelerate = function(_nohide){\n        if (!!this.__decelerator)\n            this.__decelerator = this.__decelerator._$recycle();\n        if (!_nohide){\n            this.__hideScrollBar();\n            this._$dispatchEvent('onscrollend',this.__getOffset());\n        }\n    };\n    /**\n     * 减速动画\n     *\n     * @protected\n     * @method   module:ui/scroller/scroller._$$Scroller#__doUpdateDecelerate\n     * @param    {Object} _event   - 配置参数\n     * @property {Number} offset   - 偏移量\n     * @property {Number} velocity - 当前速度\n     * @return   {Void}\n     */\n    _pro.__doUpdateDecelerate = function(_event){\n        var _offset = _event.offset,\n            _velocity = _event.velocity,\n            _distance = this.__getOutofBounce(_offset);\n        if (_distance==0){\n            this.__doScrollTo(_offset);\n            return;\n        }\n        this.__doStopDecelerate(!0);\n        this.__abopt.from.velocity = _velocity;\n        this.__abopt.from.offset = this.__bpoint[_distance<0?0:1];//this.__offset;\n        this.__bouncer = _t2._$$AnimBounce._$allocate(this.__abopt);\n        this.__bouncer._$play();\n    };\n    /**\n     * 弹性动画回收\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__doStopBounce\n     * @return {Void}\n     */\n    _pro.__doStopBounce = function(){\n        if (!!this.__bouncer)\n            this.__bouncer = this.__bouncer._$recycle();\n        this.__hideScrollBar();\n    };\n    /**\n     * 弹性动画\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__doUpdateBounce\n     * @param    {Object} _event  - 偏移量对象\n     * @property {Number} offset  - 偏移量\n     * @return {Void}\n     */\n    _pro.__doUpdateBounce = function(_event){\n        this.__doScrollTo(_event.offset);\n    };\n    /**\n     * 滚动至指定位置\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__doScrollBy\n     * @param  {Number} _delta - 偏移量\n     * @return {Void}\n     */\n    _pro.__doScrollBy = function(_delta){\n        this.__doScrollTo(this.__offset+_delta);\n    };\n    /**\n     * 滚动至指定位置\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__doScrollTo\n     * @param  {Number} _offset - 偏移量\n     * @return {Void}\n     */\n    _pro.__doScrollTo = function(_offset){\n        // 正向滚动(远离顶部的滚动)：<0\n        // 反向滚动(接近顶部的滚动)：>0\n        var _delta = _offset-this.__offset;\n        if (!_delta) return;\n        this.__offset = _offset;\n        var _distance = this.__getOutofBounce(),\n            _index = _distance<0?0:1,\n            _bounce = _distance!=0;\n        if (_bounce)\n            this.__offset = Math.ceil(this.__offset-_delta+\n                                      this.__animate.bcfactor*_delta);\n        var _map = {};\n        _map[this.__config.of] = _u._$fixed(this.__offset,2)+'px';\n        _e._$css3d(this.__cbox,'translate',_map);\n        // synchronize scrollbar\n        if (this.__barable){\n            var _offset = Math.floor(Math.max(0,-this.__scratio*this.__offset));\n            if (_bounce){\n                var _size = Math.max(8,this.__barsize-Math.abs(_distance)*2);\n                this.__body.style[this.__config.g] = _size+'px';\n                if (_distance<0)\n                    _offset = this.__boxsize-_size;\n            }else{\n                this.__body.style[this.__config.g] = this.__barsize+'px';\n                _offset = Math.min(_offset,this.__boxsize-this.__barsize);\n            }\n            var _map = {};\n            _map[this.__config.of] = _u._$fixed(_offset,2)+'px';\n            _e._$css3d(this.__body,'translate',_map);\n        }\n        // event trigger\n        if (!_bounce){\n            var _name = this.__bouncing?'onbouncend':'onscroll';\n            this.__bouncing = !1;\n            this._$dispatchEvent(_name,this.__offset);\n            return;\n        }\n        if (!!this.__skip) return;\n        var _event = {movement:_distance,\n                      direction:_delta>0?-1:1};\n        if (!!this.__bouncing){\n            this._$dispatchEvent('onbounce',_event);\n            return;\n        }\n        this.__bouncing = !0;\n        this._$dispatchEvent('onbouncestart',_event);\n    };\n    /**\n     * 开始触摸触发事件\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__onTouchStart\n     * @return {Void}\n     */\n    _pro.__onTouchStart = function(){\n        // stop all animation\n        if (!!this.__linear)\n            this.__linear._$stop();\n        if (!!this.__bouncer)\n            this.__bouncer._$stop();\n        if (!!this.__decelerator)\n            this.__decelerator._$stop();\n        if (!!this.__timer2){\n            this.__timer2 = window.clearInterval(this.__timer2);\n            this.__onTransitionEnd();\n        }\n    };\n    /**\n     * 开始事件\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__onDragStart\n     * @param  {Touch} _touch - 触点对象\n     * @return {Void}\n     */\n    _pro.__onDragStart = function(){\n        //v._$stopBubble(_event);\n        this.__refresh();\n        this.__scrolling = !0;\n        this.__showScrollBar();\n        this.__momentum.offset = this.__offset;\n        this.__momentum.time = new Date().getTime();\n    };\n    /**\n     * 过程事件\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__onDragging\n     * @param  {Touch} _touch - 触点对象\n     * @return {Void}\n     */\n    _pro.__onDragging = function(_touch){\n        if (!this.__scrolling) return;\n        var _delta = _touch.detalY;\n        this.__doScrollBy(_delta);\n        var _time = new Date().getTime();\n        if (_time-this.__momentum.time>this.__animate.reset){\n            this.__momentum.time = _time;\n            this.__momentum.offset = this.__offset;\n        }\n    };\n    /**\n     * 结束事件\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__onDragEnd\n     * @param  {Touch} _touch - 触点对象\n     * @return {Void}\n     */\n    _pro.__onDragEnd = function(_touch){\n        if (!this.__scrolling) return;\n        this.__scrolling = !1;\n        var _event = {};\n        this._$dispatchEvent('onrelease',_event);\n        var _bounce = this.__doRevertBounce(_event.offset);\n        if (!!_bounce){\n            this.__hideScrollBar();\n            return;\n        }\n        var _duration = new Date().getTime()-this.__momentum.time,\n            _distance = this.__offset-this.__momentum.offset,\n            _velocity = _distance/_duration*this.__animate.acceleration;\n        if (Math.abs(_velocity)<this.__animate.minvelocity){\n            this.__hideScrollBar();\n            this._$dispatchEvent('onscrollend',this.__getOffset());\n            return;\n        }\n        this.__adopt.from.offset = this.__offset;\n        this.__adopt.from.velocity = _velocity;\n        this.__decelerator = _t4._$$AnimDecelerate._$allocate(this.__adopt);\n        this.__decelerator._$play();\n    };\n    /**\n     * 动画结束触发事件\n     *\n     * @protected\n     * @method module:ui/scroller/scroller._$$Scroller#__onTransitionEnd\n     * @return {Void}\n     */\n    _pro.__onTransitionEnd = function(){\n        this.__cbox.style.webkitTransitionDuration = '0ms';\n    };\n    /**\n     * 控件节点追加至容器\n     * @method module:ui/scroller/scroller._$$Scroller#_$appendTo\n     * @param  {String|Node} arg0 - 控件所在容器节点\n     * @return {Void}\n     */\n    _pro._$appendTo = function(_parent){\n        this.__super();\n        this.__barable = _e._$getStyle(\n             this.__body,'display')!='none';\n        if (!this.__parent) return;\n        this.__doInitDomEvent([\n            [document,'dragging',this.__evopt.ondrag],\n            [document,'dragcomplete',this.__evopt.ondragend],\n            [this.__parent,'tapdown',this.__evopt.ontapstart],\n            [this.__parent,'dragbegin',this.__evopt.ondragstart]\n        ]);\n    };\n    /**\n     * 恢复弹性\n     * @method module:ui/scroller/scroller._$$Scroller#_$revertBounce\n     * @return {Void}\n     */\n    _pro._$revertBounce = function(){\n        if (!!this.__linear)\n            this.__linear._$stop();\n        // skip bounce event\n        this.__skip = !0;\n        this.__doRevertBounce(null,200);\n    };\n    /**\n     * 判断偏移是否在可视范围内\n     * @method module:ui/scroller/scroller._$$Scroller#_$isInViewPoint\n     * @param  {String|Node} _element - 检测节点\n     * @return {Boolean}              是否在可视范围内\n     */\n    _pro._$isInViewPoint = function(_element){\n        _element = _e._$get(_element);\n        if (!_element) return !1;\n        var _range0 = _e._$offset(_element,\n                      this.__cbox)[this.__config.of],\n            _range1 = _range0+_element.offsetHeight;\n        this.__doRefresh();\n        var _beg = Math.abs(Math.min(0,this.__offset)),\n            _end = _beg+this.__boxsize;\n        return !(_range1<_beg||_range0>_end);\n    };\n    /**\n     * 取当前滚动高度\n     * @method module:ui/scroller/scroller._$$Scroller#_$getScrollTop\n     * @return {Number} 滚动高度\n     */\n    _pro._$getScrollTop = function(){\n        this.__doRefresh();\n        return Math.abs(Math.max(this.__bpoint[0],\n                        Math.min(this.__bpoint[1],this.__offset)));\n    };\n    /**\n     * 滚动至偏移位置\n     * @method module:ui/scroller/scroller._$$Scroller#_$scrollBy\n     * @param  {Number}  _delta   - 偏移量\n     * @param  {Boolean} _refresh - 是否需要刷新\n     * @return {Void}\n     */\n    _pro._$scrollBy = function(_delta,_refresh){\n        this.__doRefresh(_refresh);\n        this._$scrollTo(Math.abs(this.__offset)+\n                                (parseInt(_delta)||0));\n    };\n    /**\n     * 滚动至指定位置\n     * @method module:ui/scroller/scroller._$$Scroller#_$scrollTo\n     * @param  {Number}  _offset  - 偏移量\n     * @param  {Boolean} _refresh - 是否需要刷新\n     * @return {Void}\n     */\n    _pro._$scrollTo = function(_offset,_refresh){\n        this.__onTouchStart();\n        this.__doRefresh(_refresh);\n        _offset = Math.max(this.__bpoint[0],\n                  Math.min(this.__bpoint[1],0-_offset));\n        _e._$setStyle(this.__cbox,'transitionDuration','150ms');\n        this.__doScrollTo(_offset);\n        if (!!this.__timer2)\n            this.__timer2 = window.clearTimeout(this.__timer2);\n        this.__timer2 = window.setTimeout(this.__evopt.ontransitionend,150);\n    };\n    /**\n     * 滚动至顶部\n     * @method module:ui/scroller/scroller._$$Scroller#_$scrollTop\n     * @param  {Boolean} _refresh - 是否需要刷新\n     * @return {Void}\n     */\n    _pro._$scrollTop = function(_refresh){\n        this.__doRefresh(_refresh);\n        this._$scrollTo(Math.abs(this.__bpoint[1]));\n    };\n    /**\n     * 滚动至中部\n     * @method module:ui/scroller/scroller._$$Scroller#_$scrollMiddle\n     * @param  {Boolean} _refresh - 是否需要刷新\n     * @return {Void}\n     */\n    _pro._$scrollMiddle = function(_refresh){\n        this.__doRefresh(_refresh);\n        this._$scrollTo((this.__bpoint[1]-this.__bpoint[0])/2);\n    };\n    /**\n     * 滚动至底部\n     * @method module:ui/scroller/scroller._$$Scroller#_$scrollBottom\n     * @param  {Boolean} _refresh - 是否需要刷新\n     * @return {Void}\n     */\n    _pro._$scrollBottom = function(_refresh){\n        this.__doRefresh(_refresh);\n        this._$scrollTo(Math.abs(this.__bpoint[0]));\n    };\n    /**\n     * 滚动到指定元素\n     * @method module:ui/scroller/scroller._$$Scroller#_$scrollToElement\n     * @param  {String|Node} _element - 目标元素\n     * @param  {Boolean}     _refresh - 是否需要刷新\n     * @return {Void}\n     */\n    _pro._$scrollToElement = function(_element,_refresh){\n        var _offset = _e._$offset(_element,this.__cbox);\n        if (!_offset) return;\n        this._$scrollTo(_offset[this.__config.of],_refresh);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/scroller/scroller.x.js",
    "content": "﻿// link to ui/scroller/x for compatible\n// use ui/scroller/x for new project\nNEJ.define(['./x.js'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/scroller/scroller.y.js",
    "content": "﻿// link to ui/scroller/y for compatible\n// use ui/scroller/y for new project\nNEJ.define(['./y.js'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/scroller/test/scroller.y.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>scrolly测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n        <style type=\"text/css\">\n        \t#scroll-y-container{height:200px;position:relative;overflow:hidden;}\n        </style>\n\t</head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit scrolly test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <div id=\"scroll-y-container\">\n        \t<div>\n        \t\t123\n        \t</div>\n        </div>\n       <script src=\"../../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./scroller.y.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/ui/scroller/test/scroller.y.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"scrolly\");\n\n\tvar _  = NEJ.P,\n\t    _p = _('nej.ui');\n\n    //开始单元测试\n    test('scrolly',function(){\n    \texpect(0);\n\t\tvar _sly = _p._$$ScrollerY._$allocate({\n\t\t\tparent:'scroll-y-container',\n\t\t\tonscroll:function(){\n\n\t\t\t},\n\t\t\tonscrollend:function(){\n\n            },\n\t\t\tonbounce:function(_event){\n\n            },\n\t\t\tonbouncend:function(_event){\n\n\t\t\t},\n\t\t\tonbouncestart:function(_event){\n\n\t\t\t},\n\t\t\tonrelease:function(){\n\n\t\t\t}\n\t\t});\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}scroller.y.test.js',['ui/scroller/scroller.y'],f);\n});"
  },
  {
    "path": "src/ui/scroller/x.css",
    "content": ".#<uispace>{position:absolute;z-index:10;$<transform>-origin:0 0;$<transition>-property:opacity;$<transition>-duration:250ms;background-color:rgba(0,0,0,0.6);$<border-radius>:4px;border:1px solid rgba(255,255,255,0.2);opacity:0;overflow:hidden;}\n.#<uispace>-view{position:relative;z-index:5;$<transform>:$<translate>;}\n.#<uispace>{bottom:1px;left:0;height:4px;}"
  },
  {
    "path": "src/ui/scroller/x.js",
    "content": "/*\n * ------------------------------------------\n * 水平滚动控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/scroller/x */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'ui/scroller/scroller',\n    'text!./x.css'\n],function(NEJ,_k,_e,_i0,_css,_p,_o,_f,_r){\n    // variable declaration\n    var _pro,\n        _seed_css = _e._$pushCSSText(_css);\n    /**\n     * 滚动配置信息\n     * @typedef  {Object} module:ui/scroller/x._$$ScrollerX~Config\n     * @property {Number} f  - h\n     * @property {Number} a  - 方向\n     * @property {Number} g  - 宽度\n     * @property {Number} t  - pageX\n     * @property {Number} of - x\n     * @property {Number} ob - offsetWidth\n     * @property {Number} sb - scrollWidth\n     * @property {Number} dx - m41\n     */\n    /**\n     * 水平滚动控件\n     *\n     * @class   module:ui/scroller/x._$$ScrollerX\n     * @extends module:ui/scroller/scroller._$$Scroller\n     * @param   {Object} arg0 - 可选配置参数\n     */\n    _p._$$ScrollerX = _k._$klass();\n    _pro = _p._$$ScrollerX._$extend(_i0._$$Scroller);\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/scroller/x._$$ScrollerX#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css = _seed_css;\n    };\n    /**\n     * 取滚动配置信息\n     *\n     * @protected\n     * @method module:ui/scroller/x._$$ScrollerX#__getConfig\n     * @return {module:ui/scroller/x._$$ScrollerX~Config} 滚动配置信息\n     */\n    _pro.__getConfig = function(){\n        return {f:'h',a:'left',g:'width',t:'pageX',of:'x',\n                ob:'offsetWidth',sb:'scrollWidth',dx:'m41'};\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/scroller/y.css",
    "content": ".#<uispace>{position:absolute;z-index:10;$<transform>-origin:0 0;$<transition>-property:opacity;$<transition>-duration:250ms;background-color:rgba(0,0,0,0.6);$<border-radius>:4px;border:1px solid rgba(255,255,255,0.2);opacity:0;overflow:hidden;}\n.#<uispace>-view{position:relative;z-index:5;$<transform>:$<translate>;}\n.#<uispace>{top:0;right:1px;width:6px;}"
  },
  {
    "path": "src/ui/scroller/y.js",
    "content": "/*\n * ------------------------------------------\n * 垂直滚动控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/scroller/y */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'ui/scroller/scroller',\n    'text!./y.css'\n],function(NEJ,_k,_e,_i0,_css,_p,_o,_f,_r){\n    // variable declaration\n    var _pro,\n        _seed_css = _e._$pushCSSText(_css);\n    /**\n     * 滚动配置信息\n     * @typedef  {Object} module:ui/scroller/y._$$ScrollerY.Config\n     * @property {Number} f  - v\n     * @property {Number} a  - 方向\n     * @property {Number} g  - 高度\n     * @property {Number} t  - pageY\n     * @property {Number} of - y\n     * @property {Number} ob - offsetHeight\n     * @property {Number} sb - scrollHeight\n     * @property {Number} dx - m42\n     */\n    /**\n     * 垂直滚动控件\n     *\n     * @class   module:ui/scroller/y._$$ScrollerY 垂直滚动控件\n     * @extends module:ui/scroller/scroller._$$Scroller\n     * @param   {Object} arg0 - 可选配置参数\n     */\n    _p._$$ScrollerY = _k._$klass();\n    _pro = _p._$$ScrollerY._$extend(_i0._$$Scroller);\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/scroller/y._$$ScrollerY#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css = _seed_css;\n    };\n    /**\n     * 取滚动配置信息\n     *\n     * @protected\n     * @method module:ui/scroller/y._$$ScrollerY#__getConfig\n     * @return {Object} 滚动配置信息\n     */\n    _pro.__getConfig = function(){\n        return {f:'v',a:'top',g:'height',t:'pageY',of:'y',\n                ob:'offsetHeight',sb:'scrollHeight',dx:'m42'};\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/scroller.list/scroller.list.js",
    "content": "﻿// link to ui/scroller/list for compatible\n// use ui/scroller/list for new project\nNEJ.define(['ui/scroller/list'],function(_t){return _t;});"
  },
  {
    "path": "src/ui/scroller.list/test/scroller.list.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>scrollList测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style type=\"text/css\">\n\t\t\t.box{position:relative;}\n\t\t\t#scrollList-box{height:200px;overflow:hidden;background:pink;}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit scrollList test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<div>\n\t\t<div id=\"scrollList-box\" class=\"box\"></div>\n\t\t</div>\n\t\t<div style=\"height:1000px;\"></div>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./scroller.list.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/ui/scroller.list/test/scroller.list.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"ui-scrollList\");\n\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _p = _('nej.ui'),\n\t\t_t = _('nej.ut');\n\n    //开始单元测试\n//    test('scrollList',function(){\n//        stop();\n//        var _scrollList = _p._$$ListScroller._$allocate({\n//            parent:'scrollList-box',\n//            onscroll:function(_offset){\n//                ok(true,'onscroll');\n//            },\n//            onbounce:function(_event){\n//                ok(true,'onbounce');\n//            },\n//            onbouncestart:function(){\n//                ok(true,'onbouncestart');\n//            },\n//            onlistupdate:function(_node){\n//                ok(true,'onlistupdate');\n//                start();\n//            },\n//            onbeforeclear:function(_box){\n//                ok(true,'onbeforeclear');\n//            }\n//        });\n//        _scrollList._$bindPuller(_p._$$PullRefresh._$allocate({\n//            onrefresh:function(){\n//                var _list = '';\n//                for(var _i = 20; _i > 0; _i--){\n//                    _list += '<div>' + _i + '</div>'\n//                }\n//                _scrollList._$addLast(_list);\n//            }\n//        }));\n//    });\n\n\ttest('profile',function(){\n        stop();\n\t\tvar _sp = _t._$$ScrollPerf._$allocate({\n            level:1,\n            offset:10,\n            viewport:'scrollList-box'\n        });\n        var _scrollList = _p._$$ListScroller._$allocate({\n            parent:'scrollList-box',\n            onscroll:function(_offset){\n                ok(true,'onscroll');\n\t\t\t\t_sp._$performance(_scrollList._$getScrollTop());\n            },\n            onbounce:function(_event){\n                ok(true,'onbounce');\n            },\n            onbouncestart:function(){\n                ok(true,'onbouncestart');\n            },\n            onlistupdate:function(_node){\n                ok(true,'onlistupdate');\n                start();\n            },\n            onbeforeclear:function(_box){\n                ok(true,'onbeforeclear');\n            }\n        });\n        _scrollList._$bindPuller(_p._$$PullRefresh._$allocate({\n            onrefresh:function(){\n                var _list = '';\n                for(var _i = 40; _i > 0; _i--){\n                    _list += '<p class=\"js-perf\">' + _i + '</p>'\n                }\n                _scrollList._$addLast(_list);\n            }\n        }));\n    });\n\n//\ttest('profile image',function(){\n//        stop();\n//        var _sp = _t._$$ScrollPerf._$allocate({\n//            level:1,\n//            offset:10,\n//            viewport:'scrollList-box'\n//        });\n//        var _scrollList = _p._$$ListScroller._$allocate({\n//            parent:'scrollList-box',\n//            onscroll:function(_offset){\n//                ok(true,'onscroll');\n//                _sp._$performance(_scrollList._$getScrollTop());\n//            },\n//            onbounce:function(_event){\n//                ok(true,'onbounce');\n//            },\n//            onbouncestart:function(){\n//                ok(true,'onbouncestart');\n//            },\n//            onlistupdate:function(_node){\n//                ok(true,'onlistupdate');\n//                start();\n//            },\n//            onbeforeclear:function(_box){\n//                ok(true,'onbeforeclear');\n//            }\n//        });\n//        _scrollList._$bindPuller(_p._$$PullRefresh._$allocate({\n//            onrefresh:function(){\n//                var _list = '';\n//                for(var _i = 40; _i > 0; _i--){\n//                    _list += '<p class=\"js-perf\">' + _i + '</p>'\n//                }\n//                _scrollList._$addLast(_list);\n//            }\n//        }));\n//    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}scroller.list.test.js',\n    ['util/profile/profile',\n     'ui/scroller.list/scroller.list',\n     'ui/pullrefresh/pullrefresh'],f);\n});"
  },
  {
    "path": "src/ui/suggest/demo/suggest.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test suggest</title>\n    <meta charset=\"utf-8\"/>\n    <style>\n      p{margin:200px 0;}\n      .abc{width:170px;}\n    </style>\n  </head>\n  <body>\n    <input type=\"text\" id=\"abc\"/>\n    <br/>\n    <input type=\"text\"/>\n    <script src=\"../../../define.js\"></script>\n    <script>\n      define([\n          '../suggest.js'\n      ],function(_i){\n          _i._$$Suggest._$allocate({\n              input:'abc',\n              clazz:'abc',\n              autofill:!1,\n              onchange:function(_event){\n                  console.log(_event);\n                  this._$setList(['1','2','3','4']);\n              },\n              onselect:function(v){\n                  console.log(v);\n              }\n          });\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/ui/suggest/suggest.css",
    "content": ".#<uispace>-parent{position:relative;}\n.#<uispace>{position:absolute;border:1px solid #aaa;background:#fff;text-align:left;visibility:hidden;}\n.#<uispace> .zitm{height:20px;line-height:20px;cursor:default;}\n.#<uispace> .js-selected{background:#1257F9;}"
  },
  {
    "path": "src/ui/suggest/suggest.html",
    "content": "{if defined(\"xlist\")&&!!xlist.length}\n  {list xlist as x}<div class=\"zitm\" data-value=\"${x}\">${x}</div>{/list}\n{/if}"
  },
  {
    "path": "src/ui/suggest/suggest.js",
    "content": "/*\n * ------------------------------------------\n * 建议提示控件封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/suggest/suggest */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/util',\n    'ui/base',\n    'util/suggest/suggest',\n    'util/template/jst',\n    'text!./suggest.css',\n    'text!./suggest.html'\n],function(NEJ,_k,_e,_u,_i,_t0,_t1,_css,_html,_p,_o,_f,_r){\n    var _seed_css = _e._$pushCSSText(_css),\n        _seed_item = _t1._$add(_html),\n        _pro;\n    /**\n     * 提示建议控件\n     *\n     * 页面结构举例\n     * ```html\n     * <input type='text' id='suggest-input' />\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/element',\n     *     'ui/suggest/suggest',\n     * ],function(_e,_i0,_p,_o,_f,_r){\n     *     var _input = _e._$get('suggest-input');\n     *     // 输入框内容变化回调\n     *     var _onchage = function(_value){\n     *         // 根据输入框的值，获取需要展示的列表，返回给控件展示\n     *         _suggest._$setList(['1','2','3','4']);\n     *     };\n     *     // 选择某一项的回调\n     *     var _onselect = function(_value){\n     *         // 返回选中的值\n     *     };\n     *     // 生成下拉列表实例\n     *     var _suggest = _i0._$$Suggest._$allocate({\n     *         input:_input,\n     *         onchange:_onchage._$bind(this),\n     *         onselect:_onselect._$bind(this)\n     *     });\n     * });\n     * ```\n     *\n     * @class     module:ui/suggest/suggest._$$Suggest\n     * @uses      module:util/suggest/suggest._$$Suggest\n     * @extends   module:ui/base._$$Abstract\n     * @param     {Object}      arg0     - 可选配置参数\n     * @property  {Node|String} input    - 输入框节点或者ID\n     * @property  {Boolean}     autofill - 是否自动填充，默认自动填充\n     */\n    /**\n     * 选中触发事件\n     *\n     * @event  module:ui/suggest/suggest._$$Suggest#onselect\n     * @param  {String} arg0 -   选中值\n     */\n    /**\n     * 输入内容变化触发事件\n     *\n     * @event  module:ui/suggest/suggest._$$Suggest#onchange\n     * @param  {String} arg0 -   输入内容\n     *\n     */\n    _p._$$Suggest = _k._$klass();\n    _pro = _p._$$Suggest._$extend(_i._$$Abstract);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:ui/suggest/suggest._$$Suggest#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__sopt = {\n            onchange:this.__onChange._$bind(this),\n            onselect:this.__onSelect._$bind(this)\n        };\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/suggest/suggest._$$Suggest#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__sopt.autofill = _options.autofill!=!1;\n        this.__sopt.input = _e._$get(_options.input);\n        this.__sopt.input.insertAdjacentElement('afterEnd',this.__body);\n        this.__suggest = _t0._$$Suggest._$allocate(this.__sopt);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/suggest/suggest._$$Suggest#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        if (!!this.__suggest){\n            this.__suggest._$recycle();\n            delete this.__suggest;\n        }\n        this.__super();\n        delete this.__sopt.input;\n    };\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/suggest/suggest._$$Suggest#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css = _seed_css;\n    };\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method module:ui/suggest/suggest._$$Suggest#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        this.__sopt.body = this.__body;\n    };\n    /**\n     * 输入内容变化触发事件\n     *\n     * @protected\n     * @method module:ui/suggest/suggest._$$Suggest#__onChange\n     * @param  {String} arg0 - 输入内容\n     * @return {Void}\n     */\n    _pro.__onChange = function(_value){\n        this._$dispatchEvent('onchange',_value);\n    };\n    /**\n     * 选中建议项触发事件\n     *\n     * @protected\n     * @method module:ui/suggest/suggest._$$Suggest#__onSelect\n     * @param  {String} arg0 - 选中值\n     * @return {Void}\n     */\n    _pro.__onSelect = function(_value,_options){\n        this._$dispatchEvent('onselect',_value,_options);\n    };\n    /**\n     * 设置建议列表\n     *\n     * 脚本举例\n     * ```javascript\n     * // 设置下拉列表的值\n     * _suggest._$setList(['1','2','3','4']);\n     * ```\n     *\n     * @method module:ui/suggest/suggest._$$Suggest#_$setList\n     * @param  {String|Array} _html  - 列表html代码或者数据列表\n     * @param  {String}       _clazz - 列表项标识样式\n     * @return {Void}\n     */\n    _pro._$setList = function(_html,_clazz){\n        if (_u._$isArray(_html))\n            _html = _t1._$get(\n                    _seed_item,{xlist:_html});\n        this.__body.innerHTML = _html||'';\n        this.__suggest._$setList(!_clazz\n            ? _e._$getChildren(this.__body)\n            : _e._$getByClassName(this.__body,_clazz));\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/ui/suggest/test/suggest.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>suggest测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">nej suggest.js test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<input type='text' id='suggest-input' />\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./suggest.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/ui/suggest/test/suggest.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"suggest\",{\n        setup:function(){\n            this._e = nej.e;\n            this._ui = nej.ui;\n        }\n    });\n\n    //开始单元测试\n    test('生成一个suggest', function() {\n        expect(0);\n        var _input = this._e._$get('suggest-input');\n        var _onchage = function(_value){\n            _suggest._$setList(['0','1','2','3','4','5','6','7','8','9']);\n        };\n        var _onselect = function(_value,_options){\n            console.log(_options.type);\n        };\n        var _suggest = this._ui._$$Suggest._$allocate({\n            input:_input,\n            onchange:_onchage._$bind(this),\n            onselect:_onselect._$bind(this)\n        });\n\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}suggest.test.js',\n    ['ui/suggest/suggest','base/element'],f);\n});\n"
  },
  {
    "path": "src/ui/timepick/demo/timepick.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>demo for colorpick</title>\n    <meta charset=\"utf-8\" />\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n  </head>\n  <body>\n    <script src=\"../../../define.js\"></script>\n    <script>\n      NEJ.define([\n          '../timepick.js'\n      ],function(_i){\n          _i._$$TimePick._$allocate({\n              format:12,\n              parent:document.body,\n              destroyable:true,\n              onchange:function(_date){\n                  log('select date -> '+_date.date);\n                  log('select date -> '+JSON.stringify(_date.clock));\n              }\n          });\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/ui/timepick/test/timepick.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>datepick测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n\t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style type=\"text/css\">\n\t\t\t#datepick-box  .js-extended{background:green;}\n\t\t\t#datepick-box  .js-selected{background:yellow;}\n            #datepick-box  .js-disabled{background:red;}\n            #datepick-box2 .js-extended{background:green;}\n            #datepick-box2 .js-selected{background:yellow;}\n            #datepick-box2 .js-disabled{background:red;}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit datepick test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<div id=\"datepick-box\"></div>\n\t\t<div id=\"datepick-box2\">\n\t\t\t<div id=\"days\"></div>\n\t\t\t<div id=\"year\"></div>\n\t\t\t<div id=\"month\"></div>\n\t\t\t<div id=\"yprv\">前一年</div>\n\t\t\t<div id=\"mprv\">前一月</div>\n\t\t\t<div id=\"ynxt\">后一年</div>\n\t\t\t<div id=\"mnxt\">后一月</div>\n\t\t</div>\n\t\t<div id=\"datepick\">jjjjjjjjjjjjj</div>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n\t\t<script type=\"text/javascript\" src=\"./datepick.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/ui/timepick/test/timepick.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"datepick\");\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _p = _('nej.ui'),\n        _ut= _('nej.ut');\n\n\n    //开始单元测试\n    test('datepick-ui',function(){\n        stop();\n        var _dp = _p._$$DatePick._$allocate({\n            parent:_e._$get('datepick-box'),\n            onchange:function(_date){\n                ok(true,'选择了一个日期，返回此日期'+_date);\n                start();\n            }\n        });\n\t\t_dp._$setDate('2012-12-21');\n\t\t_dp._$getDate();\n    });\n\n    test('datepick-util',function(){\n        expect(0);\n        var pDate = new Date(1997,7,9)\n        var nDate = new Date(2013,7,9);\n        var _days = _e._$get('days');\n        _html = _e._$add('{list 1..2 as x}<div>{list 1..6 as y}<p class=\"z-day\"></p>{/list}</div>{/list}');\n        _days.innerHTML = _e._$get(_html);\n        var _dp = _ut._$$Calendar._$allocate({\n            parent:_e._$get('datepick-box2'),\n            offset:1,\n            list:_e._$getByClassName(_days,\"z-day\"),\n            year:_e._$get('year'),\n            month:_e._$get('month'),\n            yprv:_e._$get('yprv'),\n            mprv:_e._$get('mprv'),\n            ynxt:_e._$get('ynxt'),\n            mnxt:_e._$get('mnxt'),\n            onchange:function(_date){\n                // ok(true,'日期变化'+_date);\n                // start();\n            },\n            onselect:function(_date){\n\t\t\t\t_dp._$setDate(_date)\n                // ok(true,'直接用calendar选择了一个日期，返回此日期'+_date);\n                // start();\n            },\n            range:[pDate,nDate]\n        });\n\t\t_dp._$setDate('1998-09-03');\n\t\t_dp._$getDate();\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}datepick.test.js',['ui/datepick/datepick'],f);\n});"
  },
  {
    "path": "src/ui/timepick/timepick.css",
    "content": ".#<uispace>{width:210px;border:1px solid #aaa;font-size:14px;text-align:center;}\n.#<uispace> .zact{line-height:30px;overflow:hidden;zoom:1;}\n.#<uispace> .zact .zfl{float:left;}\n.#<uispace> .zact .zfr{float:right;}\n.#<uispace> .zact .zbtn{padding:0 5px;cursor:pointer;}\n.#<uispace> .zact .ztxt{margin-left:10px;}\n.#<uispace> .zday{table-layout:fixed;border-collapse:collapse;width:100%;}\n.#<uispace> .zday th{font-weight:normal;}\n.#<uispace> .zday a{display:block;height:22px;line-height:22px;color:#333;text-decoration:none;}\n.#<uispace> .zday a:hover{background:#eee;}\n.#<uispace> .zday a.js-extended{color:#aaa;}\n.#<uispace> .zday a.js-selected,\n.#<uispace> .zday a.js-selected:hover{background:#DAE4E7;}\n.#<uispace> .zday a.js-disabled,\n.#<uispace> .zday a.js-disabled:hover{background:#fff;color:#eee;cursor:default;}\n.#<uispace> .ztime{padding-bottom:5px;padding-top:5px;font-size:0;}\n.#<uispace> .ztime .zper{width:30px;height:30px;*height:auto;line-height:30px;margin-left:10px;_margin-left:5px;border:1px solid #aaa;overflow:hidden;float:left;display:none;font-size:12px;font-size:11px\\0;}\n.#<uispace> .ztime .zper option{padding:0;margin:0;text-align:center;font-size:10px;height:14px;line-height:14px;}\n.#<uispace> .ztime input{width:20px;height:24px;line-height:24px;text-align:center;font-size:14px;}\n.#<uispace> .ztime .sep{display:inline-block;*display:inline;*zoom:1;height:30px;line-height:30px;vertical-align:top;margin-left:8px;margin-right:8px;font-size:14px;}\n.#<uispace> .ztime .zbtn-list{display:inline-block;*display:inline;*zoom:1;vertical-align:top;margin-left:10px;margin-top:-2px;}\n.#<uispace> .ztime .zbtn-list .ztimebtn{padding:1px 5px 0;display:block;height:13px;border:1px solid #aaa;font-size:10px;line-height:12px;cursor:pointer;}\n.#<uispace> .ztime .zbtn-list .ztimebtn-1{margin-top:3px;}\n.#<uispace> .zenterbtn{margin:0 10px 5px;}\n.#<uispace> .zenterbtn a{display:block;width:100%;height:20px;border:1px solid #aaa;font:14px/20px 'yahei','微软雅黑';cursor:pointer;}\n.#<uispace> .zenterbtn a:hover{background:#DAE4E7;}"
  },
  {
    "path": "src/ui/timepick/timepick.html",
    "content": "<textarea name='jst' id='#<seedDate>'>\n\t<table class=\"zday\">\n\t\t<tr>{list [\"日\",\"一\",\"二\",\"三\",\"四\",\"五\",\"六\"] as x}<th>${x}</th>{/list}</tr>\n\t\t{list 1..6 as x}\n\t\t<tr>{list 1..7 as y}<td><a href=\"javascript:void(0);\" class=\"js-ztag\"></a></td>{/list}</tr>\n\t\t{/list}\n    </table>\n</textarea>\n\n<textarea name='txt' id='#<seedAction>'>\n\t<div class=\"zact\">\n\t\t<span class=\"zbtn zfl\" title=\"上一年\">&lt;&lt;</span>\n\t\t<span class=\"zbtn zfl\" title=\"上一月\">&lt;</span>\n\t\t<span class=\"zbtn zfr\" title=\"下一年\">&gt;&gt;</span>\n\t\t<span class=\"zbtn zfr\" title=\"下一月\">&gt;</span>\n\t\t<span class=\"ztxt\"></span>年\n\t\t<span class=\"ztxt\"></span>月\n\t</div>\n</textarea>\n\n<textarea name='txt' id='#<seedTime>'>\n\t<div class=\"ztime js-clock\">\n\t\t<select class=\"zper js-ztag\" size=\"2\">\n\t\t\t<option value=\"A.M.\" selected>A.M.</option>\n\t\t\t<option value=\"P.M.\">P.M.</option>\n\t\t</select>\n\t\t<input type=\"text\" id=\"z-hour\" class=\"js-ztag\"><div class=\"sep\">:</div>\n\t\t<input type=\"text\" id=\"z-minute\" class=\"js-ztag\"><div class=\"sep\">:</div>\n\t\t<input type=\"text\" id=\"z-second\" class=\"js-ztag\">\n\t\t<div class=\"zbtn-list\">\n\t\t\t<div class=\"ztimebtn js-ztag\" id=\"ztime-add\">&#9650;</div>\n\t\t\t<div class=\"ztimebtn ztimebtn-1 js-ztag\" id=\"ztime-minus\">&#9660;</div>\n\t\t</div>\n\t</div>\n\t<div class=\"zenterbtn\">\n\t\t<a class=\"js-enter\">确认</a>\n\t</div>\n</textarea>"
  },
  {
    "path": "src/ui/timepick/timepick.js",
    "content": "/*\n * ------------------------------------------\n * 时间选择控件实现文件\n * @version  1.0\n * @author   xiejin(hzxiejin@corp.netease.com)\n * ------------------------------------------\n */\n/** @module ui/timepick/timepick */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/util',\n    'base/event',\n    'ui/layer/card.wrapper',\n    'util/clock/clock',\n    'util/template/tpl',\n    'util/template/jst',\n    'util/calendar/calendar',\n    'text!./timepick.css',\n    'text!./timepick.html'\n],function(NEJ,_k,_e,_u,_v,_i0,_t0,_t1,_t2,_t3,_css,_html,_p,_o,_f,_r){\n    var _pro,\n        _seed_html,\n        _seed_css = _e._$pushCSSText(_css),\n        _seed_ui = _t1._$parseUITemplate(_html),\n        _seed_date = _seed_ui['seedDate'],\n        _seed_action = _seed_ui['seedAction'],\n        _seed_time = _seed_ui['seedTime'];\n    /**\n     * 日期选择控件\n     *\n     * 页面结构举例\n     * ```html\n     * <style>\n     *     // 注意，样式的优先级\n     *     // 扩展 < 当前 < 禁止\n     *     #timepick-box .js-extended{background:green;}\n     *     #timepick-box .js-selected{background:yellow;}\n     *     #timepick-box .js-disabled{background:red;}\n     * </style>\n     * <div id=\"timepick-box\"></div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/element',\n     *     'ui/timepick/timepick'\n     * ],function(_e,_i0,_p,_o,_f,_r){\n     *     var pDate = new Date(1997,7,9)\n     *     var nDate = new Date(2013,7,9);\n     *     var _dp = _i0._$$TimePick._$allocate({\n     *         parent:_e._$get('timepick-box'),\n     *         // 默认选中日期\n     *         date:'2012-10-10',\n     *         // 设置日期的可选范围\n     *         range:[pDate,nDate],\n     *         onchange:function(_time){\n     *             // 选择了一个日期，返回此日期\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @class     module:ui/timepick/timepick._$$TimePick\n     * @uses      module:util/calendar/calendar._$$Calendar\n     * @extends   module:ui/layer/card._$$CardWrapper\n     * @param     {Object} arg0  - 可选配置参数\n     * @property  {Date}   date  - 设置日期\n     * @property  {Array}  range - 可选范围\n     */\n    /**\n     * 日期变化触发事件\n     *\n     * @event  module:ui/timepick/timepick._$TimePick#onchange\n     * @param  {Date} arg0 - 日期\n     *\n     */\n    _p._$$TimePick = _k._$klass();\n    _pro = _p._$$TimePick._$extend(_i0._$$CardWrapper);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:ui/timepick/timepick._$$TimePick#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__dopt = {\n            onselect:this.__onDateChange._$bind(this)\n        };\n        this.__copt = {};\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:ui/timepick/timepick._$$TimePick#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__dopt.range = _options.range;\n        this.__calendar = _t3._$$Calendar\n                            ._$allocate(this.__dopt);\n        this.__copt.format = _options.format||'24';\n        this.__clock = _t0._$$Clock\n                            ._$allocate(this.__copt);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:ui/timepick/timepick._$$TimePick#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__dopt.range;\n        delete this.__copt.format;\n        var _clock = this.__clock;\n        if (!!_clock){\n            delete this.__clock;\n            _clock._$recycle();\n        }\n        var _calendar = this.__calendar;\n        if (!!_calendar){\n            delete this.__calendar;\n            _calendar._$recycle();\n        }\n    };\n    /**\n     * 初始化外观信息\n     *\n     * @protected\n     * @method module:ui/timepick/timepick._$$TimePick#__initXGui\n     * @return {Void}\n     */\n    _pro.__initXGui = function(){\n        this.__seed_css  = _seed_css;\n        this.__seed_html = _seed_html;\n    };\n    /**\n     * 初始化节点\n     *\n     * @protected\n     * @method module:ui/timepick/timepick._$$TimePick#__initNode\n     * @return {Void}\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        var _list = _e._$getChildren(this.__body);\n        this.__dopt.list = _e._$getByClassName(_list[1],'js-ztag');\n        _list = _e._$getChildren(_list[0]);\n        this.__dopt.yprv = _list[0];\n        this.__dopt.mprv = _list[1];\n        this.__dopt.ynxt = _list[2];\n        this.__dopt.mnxt = _list[3];\n        this.__dopt.year = _list[4];\n        this.__dopt.month= _list[5];\n        var _cpnode = _e._$getByClassName(this.__body,'js-clock')[0],\n            _clds = _e._$getByClassName(_cpnode,'js-ztag');\n        this.__copt.per = _clds[0];\n        this.__copt.hour = _clds[1];\n        this.__copt.minute = _clds[2];\n        this.__copt.second = _clds[3];\n        this.__copt.cprv = _clds[4];\n        this.__copt.cnxt = _clds[5];\n\n        this.__enter = _e._$getByClassName(this.__body, 'js-enter')[0];\n        _v._$addEvent(this.__enter, 'click', this.__onClickEnter._$bind(this));\n    };\n    /**\n     * 动态构建控件节点模板\n     *\n     * @protected\n     * @method module:ui/timepick/timepick._$$TimePick#__initNodeTemplate\n     * @return {Void}\n     */\n    _pro.__initNodeTemplate = function(){\n        _seed_html = _t1._$addNodeTemplate(\n            '<div class=\"'+_seed_css+' zcard\">'+\n               _t1._$getTextTemplate(_seed_action)+\n               _t2._$get(_seed_date)+\n               _t1._$getTextTemplate(_seed_time)+\n            '</div>'\n        );\n        this.__seed_html = _seed_html;\n    };\n    /**\n     * 日期变化回调函数\n     *\n     * @protected\n     * @method module:ui/timepick/timepick._$$TimePick#__onDateChange\n     * @return {Void}\n     */\n    _pro.__onDateChange = function(){\n        // var _date = this._$getDate();\n        // try{\n        //     this._$dispatchEvent('onchange',_date);\n        // }catch(e){\n        //     // ignore\n        // }\n        // this._$hide();\n    };\n    /**\n     * 点击确认按钮\n     *\n     * @protected\n     * @method module:ui/timepick/timepick._$$TimePick#__onClickEnter\n     * @return {Void}\n     */\n    _pro.__onClickEnter = function(){\n        var _date = this._$getDate();\n        try{\n            this._$dispatchEvent('onchange',_date);\n        }catch(e){\n            // ignore\n        }\n        this._$hide();\n    };\n    /**\n     * 设置日期\n     *\n     * 脚本举例\n     * ```javascript\n     * _dp._$setDate('2012-12-21');\n     * ```\n     *\n     * @method module:ui/datepick/datepick._$$DatePick#_$setDate\n     * @param  {Date} arg0 - 日期\n     * @return {Void}\n     */\n    _pro._$setDate = function(_date){\n        _date = _u._$var2date(_date);\n        this.__calendar._$setDate(_date);\n    };\n    /**\n     * 取当前日期时间\n     *\n     * 脚本举例\n     * ```javascript\n     * // 返回一个日期时间对象\n     * var _dateTime = _dp._$getDate();\n     * ```\n     *\n     * @method module:ui/datepick/datepick._$$DatePick#_$getDate\n     * @return {Object} 日期时间对象\n     */\n    _pro._$getDate = function(){\n        return {\n            date:this.__calendar._$getDate(),\n            clock:this.__clock._$getClock()\n        };\n    };\n    /**\n     * 设置时间\n     *\n     * 脚本举例\n     * ```javascript\n     * _dp._$setClock('23:23:23');\n     * ```\n     *\n     * @method module:ui/timepick/timepick._$$TimePick#_$setClock\n     * @param  {Date|String} arg0 - 时间\n     * @return {Void}\n     */\n    _pro._$setClock = function(_time){\n        this.__clock._$setClock(_time);\n    };\n    /**\n     * 取当前时间\n     *\n     * 脚本举例\n     * ```javascript\n     * // 返回一个时间对象\n     * var _time = _dp._$getClock();\n     * ```\n     *\n     * @method module:ui/timepick/timepick._$$TimePick#_$getClock\n     * @return {Object} 时间对象\n     */\n    _pro._$getClock = function(){\n        return this.__clock._$getClock();\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ui'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/ajax/demo/a.html",
    "content": "<div>\n  <p>aaaaaaaaaaa</p>\n</div>"
  },
  {
    "path": "src/util/ajax/demo/a.js",
    "content": "console.log('111111111111');"
  },
  {
    "path": "src/util/ajax/demo/b.html",
    "content": "<script type=\"text/plain\" src=\"./a.js\"></script>\n<textarea></textarea>\n<div></div>"
  },
  {
    "path": "src/util/ajax/demo/b.json",
    "content": "{\n  \"a\":\"aaaaa\"\n}"
  },
  {
    "path": "src/util/ajax/demo/rest.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <title>test rest</title>\n    <meta charset=\"utf-8\"/>\n    <script>\n        function log(m){\n            var p = document.createElement('p');\n            p.innerHTML = m;\n            document.body.appendChild(p);\n        }\n    </script>\n</head>\n<body>\n\n<script src=\"../../../define.js\"></script>\n<script>\n    define([\n        '../rest.js'\n    ],function(_j){\n        log('begin request');\n        _j._$request('./b.json',{\n            type:'json',\n            method:'GET',\n            data:'a=aaaa&b=bbbb',\n            onload:function(result){\n                log(JSON.stringify(result));\n            },\n            onerror:function(error){\n                log(JSON.stringify(error));\n            }\n        });\n        _j._$request('/:aid/:bid/cid',{\n            type:'json',\n            method:'GET',\n            data:{aid:1,bid:2,cid:3},\n            onload:function(result){\n                log(JSON.stringify(result));\n            },\n            onerror:function(error){\n                log(JSON.stringify(error));\n            }\n        });\n    });\n</script>\n</body>\n</html>"
  },
  {
    "path": "src/util/ajax/demo/tag.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test tag</title>\n    <meta charset=\"utf-8\"/>\n    <script>\n      function log(m) {\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n\n\n    </script>\n  </head>\n  <body>\n    <input type=\"button\" value=\"加载\" onclick=\"a();\"/>\n    <script src=\"../../../define.js\"></script>\n    <script>\n      define([\n          '../tag.js'\n      ],function(_j){\n          \n          _j._$loadTemplate('./b.html',{\n              onload:function(result){\n                  log('same domain');\n                  log(result);\n              }\n          });\n\n          _j._$loadTemplate('http://localhost:8080/nej/src/util/ajax/demo/b.html',{\n              onload: function(result){\n                  log('same domain');\n                  log(result);\n              }\n          });\n\n          window.a = function (){\n              _j._$loadTemplate('http://a.b.com:8080/nej/src/util/ajax/demo/b.html',{\n                  onload: function(result){\n                      log('cross domain');\n                      log(result);\n                  }\n              });\n          };\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/ajax/demo/upload.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test file upload</title>\n    <meta charset=\"utf-8\"/>\n  </head>\n  <body>\n    \n    <script src=\"../../../../src/define.js\"></script>\n    <script>\n      define([\n          '../tag.js'\n      ],function(_j){\n          \n          _j._$loadHtml('./a.html',{\n              onload:function(result){\n                  console.log(result);\n              }\n          });\n          \n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/ajax/demo/xdr.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test xdr</title>\n    <meta charset=\"utf-8\"/>\n  </head>\n  <body>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n      define([\n          '../xdr.js',\n          '../rest.js'\n      ],function(_j,_r){\n          \n          _j._$request('./D.json',{\n              query:{b:'bbb'},\n              data:'a=aaaa',\n              onload:function(result){\n                  console.log(result);\n              }\n          });\n          \n          _r._$request('./D.json',{\n              query:{b:'bbb'},\n              data:'a=aaaa',\n              onload:function(result){\n                  console.log(result);\n              },\n              onerror:function(error){\n                  console.log(error);\n              }\n          });\n          \n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/ajax/dwr.js",
    "content": "/*\n * ------------------------------------------\n * DWR框架前端引擎实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/ajax/dwr */\nNEJ.define([\n    'base/global',\n    'base/constant',\n    'base/util',\n    'util/ajax/xdr',\n    'util/ajax/tag',\n    'util/cache/cookie'\n],function(NEJ,_g,_u,_j0,_j1,_j2,_p,_o,_f,_r){\n    var _batchid,         // 请求ID标识\n        _doFilter = _f,   // 全局异常过滤器\n        _xcache   = {},   // 请求缓存\n        _cname    = 'JSESSIONID',\n        _xbatch   = null; // 请求临时构造对象，范例\n                          // {h:{0:{c:function(){},   // callback\n                          //        e:function(){}}}, // exception\n                          //  p:1,                    // param number\n                          //  u:'http://xxxx/x.x.dwr',// url\n                          //  r:{script:!1,sync:!1,method:'POST',timeout:null}\n                          //                          // request options\n                          //  m:{}}                   // send data\n    /**\n     * 设置全局异常过滤器\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/dwr'\n     * ],function(_j){\n     *     // 所有请求对错误码是401的情况不做处理\n     *     _j._$setFilter(function(_event){\n     *         // _event.code\n     *         // _event.message\n     *\n     *         return _event.code == 401;\n     *     });\n     * });\n     * ```\n     *\n     * @method module:util/ajax/dwr._$setFilter\n     * @param  {Function}  arg0 - 过滤器,过滤器返回值\n     *\n     * * true  - 不继续执行后续错误处理接口\n     * * false - 继续执行后续错误处理接口\n     *\n     * @return {Void}\n     */\n    _p._$setFilter = function(_filter){\n        _doFilter = _u._$isFunction(_filter)?_filter:_f;\n    };\n    /**\n     * 设置CSRF使用的cookie名，请求时会将此cookie对应的值带在参数上发送到服务器\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/dwr'\n     * ],function(_j){\n     *     _j._$setCookieName('CSRF-CKN');\n     *\n     *     // 假设cookie里有CSRF-CKN的值为asldjsdi23234asdfasdf\n     *     // 则以下请求参数中带有httpSessionId=asldjsdi23234asdfasdf\n     *     // 服务器端取请求参数中的httpSessionId值与cookie中的CSRF-CKN值比较，判断是否是伪造请求\n     *     _j._$request(\n     *         'DownloadBean.getDownloadUrlByBrandAndModel1',{\n     *             path:'/dwr/call/plaincall/',\n     *             script:false,\n     *             param:[\"nokia\",\"n97\"],\n     *             onload:function(data){\n     *                 // TODO\n     *             },onerror:function(error){\n     *                 // TODO\n     *             }\n     *         }\n     *     );\n     * });\n     * ```\n     *\n     * @method module:util/ajax/dwr._$setCookieName\n     * @param  {String} arg0 - cookie名称\n     * @return {Void}\n     */\n    _p._$setCookieName = function(_name){\n        _cname = _name||_cname;\n    };\n    /**\n     * 设置请求标识\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/dwr'\n     * ],function(_j){\n     *     // 手动设置请求标识\n     *     _j._$setBatchId('batchId-12345');\n     * });\n     * ```\n     *\n     * @method module:util/ajax/dwr._$setBatchId\n     * @param  {String} arg0 - 请求标识\n     * @return {Void}\n     */\n    _p._$setBatchId = function(_id){\n        _batchid = _id||'';\n    };\n    /**\n     * 开始批处理请求<br/>\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/dwr'\n     * ],function(_j){\n     *     _j._$begin();\n     *     _j._$request(\n     *         'DownloadBean.getDownloadUrlByBrandAndModel1',{\n     *             path:'/dwr/call/plaincall/',\n     *             script:false,\n     *             param:[\"nokia\",\"n97\"],\n     *             onload:function(data){\n     *                 // TODO\n     *             },onerror:function(error){\n     *                 // TODO\n     *             }\n     *         }\n     *     );\n     *     _j._$request(\n     *         'DownloadBean.getDownloadUrlByBrandAndModel2',{\n     *             path:'/dwr/call/plaincall/',\n     *             script:false,\n     *             param:[\"nokia\",\"n98\"],\n     *             onload:function(data){\n     *                 // TODO\n     *             },onerror:function(error){\n     *                 // TODO\n     *             }\n     *         }\n     *     );\n     *     // 最后做一次请求发送\n     *     _j._$end();\n     * });\n     * ```\n     *\n     * @method module:util/ajax/dwr._$begin\n     * @see    module:util/ajax/dwr._$end\n     * @return {Void}\n     */\n    _p._$begin = function(){\n        if (!!_xbatch) return;\n        _xbatch = {\n            h:{},p:0,\n            m:{\n                callCount:0,\n                scriptSessionId:'${scriptSessionId}190',\n                httpSessionId:_j2._$cookie(_cname)\n            },\n            r:{\n                script:!1,\n                sync:!1,\n                method:'POST',\n                timeout:null,\n                proxy:!0,\n                cookie:!1,\n                onbeforerequest:null\n            }\n        };\n    };\n    /**\n     * 使用DWR方式载入数据\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/dwr'\n     * ],function(_j){\n     *     _j._$request(\n     *         'LogBean.log',{\n     *             path:'/dwr/call/plaincall/',\n     *             script:true,param:{},\n     *             onload:function(data){\n     *                 // 正常回调方法\n     *             },\n     *             onerror:function(error){\n     *                 // 异常回调\n     *             },\n     *             onbeforerequest:function(data){\n     *                // 请求发送前对请求数据进行处理\n     *             }\n     *         }\n     *     );\n     * });\n     * ```\n     *\n     * @method   module:util/ajax/dwr._$request\n     * @param    {String}  arg0    - 请求地址,格式为class.method\n     * @param    {Object}  arg1    - 可选配置参数\n     * @property {String}  path    - 请求路径,默认为/dwr/call/plaincall/\n     * @property {String}  query   - 请求地址附带的查询参数,格式a=aaa&b=bbb\n     * @property {Array}   param   - 参数列表,不传或空数组均作为无参数处理\n     * @property {String}  proxy   - 代理标识，使用该代理时忽略script/sync/method/timeout属性\n     * @property {Boolean} script  - 使用脚本方式载入\n     * @property {Boolean} sync    - 是否同步请求,使用脚本载入方式忽略此属性\n     * @property {String}  method  - 请求方式,GET/POST,使用脚本载入方式忽略此属性\n     * @property {Number}  timeout - 请求超时时间\n     * @property {Object}  headers - 头信息,批处理请求合并所有头信息,同名的头信息后面请求覆盖前面请求\n     * @property {String}  session - CSRF验证的COOKIE名称\n     *\n     * @property {module:util/ajax/xdr.onload}          onload  - 数据载入回调\n     * @property {module:util/ajax/xdr.onerror}         onerror - 请求异常回调\n     * @property {module:util/ajax/xdr.onbeforerequest} onbeforerequest - 请求之前回调\n     *\n     * @return   {Void}\n     */\n    _p._$request = function(_url,_options){\n        var _info = (_url||'').split('.');\n        if (!_info||_info.length!=2) return;\n        var _single = !1;\n        _options = _options||_o;\n        if (!_xbatch){\n            _single = !0;\n            _p._$begin();\n            if (!!_options.session){\n                _xbatch.m.httpSessionId = _j2._$cookie(_options.session);\n            }\n        }\n        _xbatch.u = (_options.path||'/dwr/call/plaincall/')+\n                    (_options.query&&('?'+_options.query)||'');\n        _u._$fetch(_xbatch.r,_options);\n        var _headers = _u._$merge(\n            _xbatch.r.headers,_options.headers\n        );\n        _headers[_g._$HEAD_CT] = _g._$HEAD_CT_PLAN;\n        _xbatch.r.headers = _headers;\n        var _prefix = 'c'+_xbatch.m.callCount;\n        _xbatch.m[_prefix+'-scriptName'] = _info[0];\n        _xbatch.m[_prefix+'-methodName'] = _info[1];\n        _xbatch.m[_prefix+'-id'] = _xbatch.m.callCount;\n        _xbatch.h[_xbatch.m.callCount] = {\n            c:_options.onload||_f,\n            e:_options.onerror||_f\n        };\n        _u._$forEach(\n            _options.param,function(v,i){\n                var _value = __doSerialize(v,_prefix);\n                if (!!_value){\n                    _xbatch.m[_prefix+'-param'+i] = _value;\n                }\n            }\n        );\n        _xbatch.m.callCount++;\n        if (_single){\n            _p._$end();\n        }\n    };\n    /**\n     * 结束请求批处理，正式发送请求\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/dwr'\n     * ],function(_j){\n     *     _j._$begin();\n     *     _j._$request(\n     *         'DownloadBean.getDownloadUrlByBrandAndModel1',{\n     *             path:'/dwr/call/plaincall/',\n     *             script:false,\n     *             param:[\"nokia\",\"n97\"],\n     *             onload:function(data){\n     *                 // TODO\n     *             },onerror:function(error){\n     *                 // TODO\n     *             }\n     *         }\n     *     );\n     *     _j._$request(\n     *         'DownloadBean.getDownloadUrlByBrandAndModel2',{\n     *             path:'/dwr/call/plaincall/',\n     *             script:false,\n     *             param:[\"nokia\",\"n98\"],\n     *             onload:function(data){\n     *                 // TODO\n     *             },onerror:function(error){\n     *                 // TODO\n     *             }\n     *         }\n     *     );\n     *     // 最后做一次请求发送\n     *     _j._$end();\n     * });\n     * ```\n     *\n     * @method module:util/ajax/dwr._$end\n     * @see    module:util/ajax/dwr._$begin\n     * @return {Void}\n     */\n    _p._$end = function(){\n        if (!_xbatch||!_xbatch.u){\n            _xbatch = null;\n            return;\n        }\n        var _bid = _batchid||_u._$uniqueID();\n        _batchid = 0;\n        _xbatch.m.batchId = _bid;\n        _xcache[_bid] = _xbatch;\n        _xbatch = null;\n        __doRequest(_bid);\n    };\n    /*\n     * 销毁请求对象\n     * @param  {String} 请求对象标识\n     * @return {Void}\n     */\n    var __doDestroyBatch = function(_bid){\n        var _batch = _xcache[_bid];\n        if (!_batch) return;\n        delete _batch.h;\n        delete _batch.m;\n        delete _xcache[_bid];\n    };\n    /*\n     * 序列化数据\n     * @param  {Variable} 数据\n     * @param  {String}   前缀\n     * @return {String}   序列化后的字串\n     */\n    var __doSerialize = function(_data,_prefix){\n        if (_data==null){\n            return 'null:null';\n        }\n        if (_u._$isBoolean(_data)){\n            return 'boolean:'+!!_data;\n        }\n        if (_u._$isNumber(_data)){\n            return 'number:'+_data;\n        }\n        if (_u._$isString(_data)){\n            return 'string:'+encodeURIComponent(_data);\n        }\n        if (_u._$isDate(_data)){\n            return 'Date:'+_data.getTime();\n        }\n        if (_u._$isArray(_data)){\n            return __doSerializeArray(_data,_prefix);\n        }\n        if (_u._$isObject(_data)){\n            return __doSerializeObject(_data,_prefix);\n        }\n        if (_u._$isFunction(_data,'function')){\n            return '';\n        }\n        return 'default:'+_data;\n    };\n    /*\n     * 序列化数组\n     * @param  {Array}  _data   数组\n     * @param  {String} _prefix 前缀\n     * @return {String}         序列化后的字串\n     */\n    var __doSerializeArray = function(_list,_prefix){\n        var _arr = [];\n        _u._$forEach(\n            _list,function(v,i){\n                _xbatch.p++;\n                var _ref = _prefix+'-e'+_xbatch.p,\n                    _value = __doSerialize(v,_prefix);\n                if (!_value) return;\n                _xbatch.m[_ref] = _value;\n                _arr.push('reference:'+_ref);\n            }\n        );\n        return 'Array:['+_arr.join(',')+']';\n    };\n    /*\n     * 序列化对像\n     * @param  {Array}  _data   对像\n     * @param  {String} _prefix 前缀\n     * @return {String}         序列化后的字串\n     */\n    var __doSerializeObject = function(_object,_prefix){\n        var _arr = [];\n        _u._$forIn(\n            _object,function(v,k){\n                _xbatch.p++;\n                var _ref = _prefix+'-e'+_xbatch.p,\n                    _value = __doSerialize(v,_prefix);\n                if (!_value) return;\n                _xbatch.m[_ref] = _value;\n                _arr.push(encodeURIComponent(k)+':reference:'+_ref);\n            }\n        );\n        return 'Object_Object:{'+_arr.join(',')+'}';\n    };\n    /*\n     * 序列化要发送的数据\n     * @param  {Object} _data 数据对象\n     * @param  {String} _sep  数据分隔符\n     * @return {String}       数据字符串\n     */\n    var __doSerializeSendData = function(_data,_sep){\n        if (!_data) return null;\n        var _arr = [],\n            _and = _sep=='&';\n        _u._$forIn(\n            _data,function(v,k){\n                _arr.push(\n                    !_and ? (k+'='+v) :\n                    (encodeURIComponent(k)+'='+encodeURIComponent(v))\n                );\n            }\n        );\n        return _arr.join(_sep||'\\n');\n    };\n    /*\n     * 发送请求\n     * @param  {String} _bid 请求标识\n     * @return {Void}\n     */\n    var __doRequest = function(_bid){\n        var _batch = _xcache[_bid];\n        if (!_batch) return;\n        _batch.u = _batch.u.replace(/(\\?|$)/,(\n                   _batch.m.callCount>1\n                   ?'Multiple.'+_batch.m.callCount\n                   :_batch.m['c0-scriptName']+'.'+\n                    _batch.m['c0-methodName'])+'.dwr$1');\n        var _option = _batch.r,\n            _script = !!_option.script,\n            _ispost = _option.method=='POST';\n        delete _batch.r;\n        delete _option.script;\n        _option.method = _option.method.toUpperCase();\n        _option.onerror = __onErrorWithReq._$bind(null,_bid);\n        if (_script||!_ispost){\n            _batch.u += (_batch.u.indexOf('?')>=0?'&':'?')\n                        +__doSerializeSendData(_batch.m,'&');\n        }\n        if (_script){\n            _j1._$loadScript(_batch.u,_option);\n        }else{\n            _option.onload = __onLoadWithXDR._$bind(null,_bid);\n            _option.data = _ispost?__doSerializeSendData(_batch.m):null;\n            _j0._$request(_batch.u,_option);\n        }\n    };\n    /*\n     * 单个接口出错处理\n     * @param  {String} _bid   请求标识\n     * @param  {String} _cid   接口标识\n     * @param  {Object} _error 错误信息\n     * @return {Void}\n     */\n    var __onError = function(_bid,_cid,_error){\n        var _batch = _xcache[_bid];\n        if (!_batch||_doFilter(_error)) return;\n        var _handler = _batch.h[_cid];\n        if (!_handler) return;\n        try{\n            (_handler.e||f)(_error);\n        }catch(ex){\n            // ignore\n            if (DEBUG) throw ex;\n            console.error(ex.message);\n            console.error(ex);\n        }\n    };\n    /*\n     * 整个请求出错处理\n     * @param  {String} _bid   请求标识\n     * @param  {Object} _error 错误信息\n     * @return {Void}\n     */\n    var __onErrorAll = function(_bid,_error){\n        var _batch = _xcache[_bid];\n        if (!_batch) return;\n        _u._$forIn(\n            _batch.h,function(v,k){\n                __onError(_bid,k,_error);\n            }\n        );\n    };\n    /*\n     * 数据加载成功回调函数\n     * @param  {String}   _bid  请求ID\n     * @param  {String}   _cid  回调ID\n     * @param  {Variable} _data 数据内容\n     * @return {Void}\n     */\n    var __onLoadFromDWR = function(_bid,_cid,_data){\n        var _batch = _xcache[_bid];\n        if (!_batch) return;\n        try{\n            (_batch.h[_cid].c||f)(_data);\n        }catch(ex){\n            console.log(_batch);\n            __onError(\n                _bid,_cid,{\n                    code:_g._$CODE_ERRCABK,\n                    message:'DWR回调执行异常：'+ex.message||ex\n                }\n            );\n        }\n    };\n    /*\n     * 数据载入回调\n     * @param  {String} _bid  请求标识\n     * @param  {String} _text 返回数据内容\n     * @return {Void}\n     */\n    var __onLoadWithXDR = function(_bid,_text){\n        try{\n            !!_text&&_text.search('//#DWR')>=0\n            ? (new Function(_text))()\n            : __onErrorAll(_bid,{\n                  code:_g._$CODE_ERRSERV,\n                  message:'DWR请求返回数据不合法!'\n              });\n        }catch(ex){\n            __onErrorAll(_bid,{\n                code:_g._$CODE_ERREVAL,\n                message:'DWR返回脚本执行异常：'+(ex.message||ex)\n            });\n        }finally{\n            __doDestroyBatch(_bid);\n        }\n    };\n    /*\n     * 数据载入异常\n     * @param  {String} _bid   请求标识\n     * @param  {Object} _error 错误信息\n     * @return {Void}\n     */\n    var __onErrorWithReq = function(_bid,_error){\n        __onErrorAll(_bid,_error);\n        __doDestroyBatch(_bid);\n    };\n\n    // DWR2 Adapter\n    this.dwr = this.dwr||{};\n    var w = dwr.engine = dwr.engine||{};\n    w['_remoteHandleCallback'] = __onLoadFromDWR;\n    w['_remoteHandleException'] = __onError;\n    w['_remoteHandleBatchException'] = __onErrorAll;\n    // DWR3 Adapter\n    dwr['_'] = [{\n        handleCallback:w['_remoteHandleCallback'],\n        handleException:w['_remoteHandleException'],\n        handleBatchException:w['_remoteHandleBatchException']\n    }];\n\n    if (CMPT){\n        var _j = NEJ.P('nej.j');\n        _j._$endBatch      = _p._$end;\n        _j._$requestByDWR  = _p._$request;\n        _j._$beginBatch    = _p._$begin;\n        _j._$setFilter     = _p._$setFilter;\n        _j._$setBatchId    = _p._$setBatchId;\n        _j._$setCookieName = _p._$setCookieName;\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/jsonp.js",
    "content": "/*\n * ------------------------------------------\n * JSONP控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/ajax/jsonp */\nNEJ.define([\n    'base/util',\n    './tag.js'\n],function(u, j, exports){\n    /**\n     * 发送 jsonp 请求\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/jsonp'\n     * ],function(j){\n     *     var id = j._$request(\n     *         'http://a.b.com/api',{\n     *             query:'a=1&b=2',\n     *             onload:function(_data){\n     *                 // 正常回调处理\n     *             }\n     *         }\n     *     );\n     * });\n     * ```\n     *\n     * @method   module:util/ajax/jsonp._$request\n     * @param    {String}   arg0 - 请求地址\n     * @param    {Object}   arg1 - 配置参数\n     * @property {Variable} data - 查询参数,字符串格式a=b&c=d,对象格式{a:'b',c:'d'}\n     *\n     * @property {module:util/ajax/xdr.onload}  onload  - 数据载入回调\n     *\n     * @return   {String} 分配给请求的ID\n     */\n    exports._$request = (function(){\n        var merge = function (url, data, callback) {\n            url += (url.indexOf('?')<0?'?':'&')\n                +  'callback='+callback;\n            if (!!data){\n                if (u._$isObject(data)){\n                    data = u._$object2query(data);\n                }\n                url += '&'+data;\n            }\n            return url;\n        };\n        return function (url, options) {\n            var sn = u._$uniqueID(),\n                cb = 'cb_'+sn,\n                url = merge(url, options.data, cb);\n            if (!!options.onload){\n                window[cb] = function (result) {\n                    options.onload(result);\n                    u._$safeDelete(window,cb);\n                };\n            }\n            var opt = u._$merge({},options);\n            opt.onload = null;\n            opt.onerror = function (error) {\n                if (options.onerror){\n                    u._$safeDelete(window,cb);\n                    options.onerror(error);\n                }\n            };\n            j._$loadScript(url,opt);\n            return sn;\n        };\n    })();\n});\n"
  },
  {
    "path": "src/util/ajax/loader/html.js",
    "content": "/*\n * ------------------------------------------\n * HTML资源加载器实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/ajax/loader/html */\nNEJ.define([\n    './loader.js',\n    'base/klass',\n    'base/element',\n    '{platform}html.js'\n],function(_t,_k,_e,_h,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * HTML资源加载器\n     * \n     * @class   module:util/ajax/loader/html._$$LoaderHtml\n     * @extends module:util/ajax/loader/loader._$$LoaderAbstract\n     * \n     * @param   {Object} config - 可选配置参数\n     */\n    _p._$$LoaderHtml = _k._$klass(); \n    _pro = _p._$$LoaderHtml._$extend(_t._$$LoaderAbstract);\n    /**\n     * 取资源载入控件\n     * \n     * @protected\n     * @method module:util/ajax/loader/html._$$LoaderHtml#__getRequest\n     * @return {Node} IFrame节点\n     */\n    _pro.__getRequest = function(){\n        var _iframe = _e._$create('iframe');\n        _iframe.width = 0;\n        _iframe.height = 0;\n        _iframe.style.display = 'none';\n        return _iframe;\n    };\n    /**\n     * 资源载入\n     * \n     * @protected\n     * @method module:util/ajax/loader/html._$$LoaderHtml#__doRequest\n     * @param  {Node} arg0 - 控件节点\n     * @return {Void}\n     */\n    _pro.__doRequest = function(_request){\n        try{\n            // append first for history bug\n            document.body.appendChild(_request);\n            _request.src = this.__url;\n        }catch(ex){\n            console.log(_request);\n            console.error(ex);\n        }\n    };\n    /**\n     * 资源载入异常事件\n     * \n     * @protected\n     * @method module:util/ajax/loader/html._$$LoaderHtml#__onError\n     * @param  {Object} arg0 - 错误信息\n     * @return {Void}\n     */\n    _pro.__onError = function(_error){\n        var _iframe = (\n            this.__getLoadData(this.__url)||_o\n        ).request;\n        this.__doCallback('onerror',_error);\n        _h.__removeIFrameKeepHistory(_iframe);\n    };\n    /**\n     * 资源载入成功事件\n     * \n     * @protected\n     * @method module:util/ajax/loader/html._$$LoaderHtml#__onLoaded\n     * @return {Void}\n     */\n    _pro.__onLoaded = function(){\n        var _body = null,\n            _iframe = (this.__getLoadData(this.__url)||_o).request;\n        try{\n            if (_iframe.src!=this.__url) return;\n            _body = _iframe.contentWindow.document.body;\n        }catch(ex){\n            // ignore\n        }\n        this.__doCallback('onload',_body);\n        _h.__removeIFrameKeepHistory(_iframe);\n    };\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/loader/loader.js",
    "content": "/*\n * ------------------------------------------\n * 资源加载器实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/ajax/loader/loader */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/constant',\n    'base/event',\n    'base/util',\n    'util/event'\n],function(NEJ,_k,_g,_v,_u,_t,_p,_o,_f,_r){\n    var _pro,\n        _timeout = 60000;\n    /**\n     * 资源加载器\n     * \n     * @class    module:util/ajax/loader/loader._$$LoaderAbstract\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object} config  - 可选配置参数\n     * @property {String} version - 版本信息\n     * @property {Number} timeout - 超时时间，0表示禁止超时监测\n     */\n    /** \n     * 资源载入失败回调\n     * \n     * @event    module:util/ajax/loader/loader._$$LoaderAbstract#onerror\n     * @param    {Object} event   - 错误信息\n     * @property {Number} code    - 错误码\n     * @property {String} message - 错误信息\n     */\n    /** \n     * 资源载入成功回调\n     * \n     * @event  module:util/ajax/loader/loader._$$LoaderAbstract#onload\n     * @param  {Variable} event - 请求返回数据\n     */\n    /** \n     * 资源加载中回调\n     * \n     * @event  module:util/ajax/loader/loader._$$LoaderAbstract#onloading\n     */\n    _p._$$LoaderAbstract = _k._$klass();\n    _pro = _p._$$LoaderAbstract._$extend(_t._$$EventTarget);\n    /**\n     * 控件初始化\n     * \n     * @protected\n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__super();\n        this.__qopt = {\n            onerror:this.__onQueueError._$bind(this),\n            onload:this.__onQueueLoaded._$bind(this)\n        };\n        if (!this.constructor.__cache){\n            // url : {request:script,timer:2,bind:[instance1,instance2 ... ]}\n            // key : {error:0,loaded:0,total:0,bind:[instance1,instance2 ... ]}\n            this.constructor.__cache = {loaded:{}};\n        }\n    };\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__version = _options.version;\n        this.__timeout = _options.timeout;\n        this.__qopt.version = this.__version;\n        this.__qopt.timeout = this.__timeout;\n    };\n    /**\n     * 删除加载信息\n     * \n     * @protected\n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#__delLoadData\n     * @param  {String} arg0 - 标识\n     * @return {Object}        加载信息\n     */\n    _pro.__delLoadData = function(_key){\n        delete this.constructor.__cache[_key];\n    };\n    /**\n     * 取加载信息\n     * \n     * @protected\n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#__getLoadData\n     * @param  {String} arg0 - 标识\n     * @return {Object}        加载信息\n     */\n    _pro.__getLoadData = function(_key){\n        return this.constructor.__cache[_key];\n    };\n    /**\n     * 设置加载信息\n     * \n     * @protected\n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#__setLoadData\n     * @param  {String} arg0 - 标识\n     * @param  {Object} arg1 - 加载信息\n     * @return {Void}\n     */\n    _pro.__setLoadData = function(_key,_data){\n        this.constructor.__cache[_key] = _data;\n    };\n    /**\n     * 取资源载入控件，子类实现具体逻辑\n     * \n     * @abstract\n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#__getRequest\n     * @return {Script|Link} 控件\n     */\n    _pro.__getRequest = _f;\n    /**\n     * 清理控件\n     * \n     * @protected\n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#__doClearRequest\n     * @param  {Script|Link} arg0 - 控件\n     * @return {Void}\n     */\n    _pro.__doClearRequest = function(_request){\n        _v._$clearEvent(_request);\n    };\n    /**\n     * 资源载入\n     * \n     * @protected\n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#__doRequest\n     * @param  {Script|Link} arg0 - 控件\n     * @return {Void}\n     */\n    _pro.__doRequest = function(_request){\n        _request.src = this.__url;\n        document.head.appendChild(_request);\n    };\n    /**\n     * 执行清理任务\n     * \n     * @protected\n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#__doClear\n     * @return {Void}\n     */\n    _pro.__doClear = function(){\n        var _cache = this.__getLoadData(this.__url);\n        if (!_cache) return;\n        window.clearTimeout(_cache.timer);\n        this.__doClearRequest(_cache.request);\n        delete _cache.bind;\n        delete _cache.timer;\n        delete _cache.request;\n        this.__delLoadData(this.__url);\n        this.__getLoadData('loaded')[this.__url] = !0;\n    };\n    /**\n     * 执行回调\n     * \n     * @protected\n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#__doCallback\n     * @param  {String} arg0 - 回调名称\n     * @return {Void}\n     */\n    _pro.__doCallback = function(_name){\n        var _cache = this.__getLoadData(this.__url);\n        if (!_cache) return;\n        var _list = _cache.bind;\n        this.__doClear();\n        if (!!_list&&_list.length>0){\n            var _instance;\n            while(_list.length){\n                _instance = _list.shift();\n                try{\n                    _instance._$dispatchEvent(_name,arguments[1]);\n                }catch(ex){\n                    // ignore\n                    if (DEBUG) throw ex;\n                    console.error(ex.message);\n                    console.error(ex.stack);\n                }\n                _instance._$recycle();\n            }\n        }\n    };\n    /**\n     * 资源载入异常事件\n     * \n     * @protected\n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#__onError\n     * @param  {Object} arg0 - 错误信息\n     * @return {Void}\n     */\n    _pro.__onError = function(_error){\n        this.__doCallback('onerror',_error);\n    };\n    /**\n     * 资源载入成功事件\n     * \n     * @protected\n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#__onLoaded\n     * @return {Void}\n     */\n    _pro.__onLoaded = function(){\n        this.__doCallback('onload');\n    };\n    /**\n     * 载入队列资源\n     * \n     * @protected\n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#__doLoadQueue\n     * @param  {String} arg0 - 资源地址\n     * @return {Void}\n     */\n    _pro.__doLoadQueue = function(_url){\n        this.constructor._$allocate(this.__qopt)._$load(_url);\n    };\n    /**\n     * 检查队列状况\n     * \n     * @protected\n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#__onQueueCheck\n     * @return {Void}\n     */\n    _pro.__onQueueCheck = function(_error){\n        var _cache = this.__getLoadData(this.__key);\n        if (!_cache) return;\n        if (!!_error) \n            _cache.error++;\n        _cache.loaded ++;\n        if (_cache.loaded<_cache.total) return;\n        this.__delLoadData(this.__key);\n        this._$dispatchEvent(_cache.error>0?'onerror':'onload');\n    };\n    /**\n     * 队列载入资源异常事件\n     * \n     * @protected\n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#__onQueueError\n     * @param  {Object} arg0 - 错误信息\n     * @return {Void}\n     */\n    _pro.__onQueueError = function(_error){\n        this.__onQueueCheck(!0);\n    };\n    /**\n     * 队列载入资源成功事件\n     * \n     * @protected\n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#__onQueueLoaded\n     * @return {Void}\n     */\n    _pro.__onQueueLoaded = function(){\n        this.__onQueueCheck();\n    };\n    /**\n     * 载入资源\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/loader/html',\n     *     'util/ajax/loader/style',\n     *     'util/ajax/loader/script'\n     * ],function(_t0,_t1,_t2){\n     *     // 载入指定html,10秒超时\n     *     var _loader = _t0._$$LoaderHtml._$allocate({\n     *         timeout:10000,\n     *         onload:function(){\n     *             // 载入资源成功的回调\n     *         }\n     *     });\n     *     // 绝对路径或者当前页面的相对路径\n     *     _loader._$load('../../../html/util/formTest.html');\n     * \n     *     // 载入指定script,20秒超时\n     *     var _loader = _t2._$$LoaderScript._$allocate({\n     *         timeout:20000,\n     *         onload:function(){\n     *             // 载入资源成功的回调\n     *         }\n     *     });\n     *     // 绝对路径或者当前页面的相对路径\n     *     _loader._$load('../../../javascript/log.js');\n     * \n     *     // 载入指定style,30秒超时\n     *     var _loader = _t1._$$LoaderStyle._$allocate({\n     *         timeout:30000,\n     *         onload:function(){\n     *             // 载入资源成功的回调\n     *         }\n     *     });\n     *     // 绝对路径或者当前页面的相对路径\n     *     _loader._$load('../../../base/qunit.css');\n     * });\n     * ```\n     * \n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#_$load\n     * @param  {String} arg0 - 资源地址\n     * @return {Void}\n     */\n    _pro._$load = function(_url){\n        _url = _u._$absolute(_url);\n        if (!_url){\n            this._$dispatchEvent('onerror',{\n                code:_g._$CODE_NOTASGN,\n                message:'请指定要载入的资源地址！'\n            });\n            return;\n        };\n        this.__url = _url;\n        if (!!this.__version){\n            this.__url += (this.__url.indexOf('?')<0?'?':'&')+this.__version;\n        }\n        if (this.__getLoadData('loaded')[this.__url]){\n            try{\n                this._$dispatchEvent('onload');\n            }catch(ex){\n                // ignore\n                if (DEBUG) throw ex;\n                console.error(ex.message);\n                console.error(ex.stack);\n            }\n            this._$recycle();\n            return;\n        }\n        var _cache = this.__getLoadData(this.__url),_request;\n        if (!!_cache){\n            _cache.bind.unshift(this);\n            _cache.timer = window.clearTimeout(_cache.timer);\n        }else{\n            _request = this.__getRequest();\n            _cache = {request:_request,bind:[this]};\n            this.__setLoadData(this.__url,_cache);\n            _v._$addEvent(\n                _request,'load',\n                this.__onLoaded._$bind(this)\n            );\n            _v._$addEvent(\n                _request,'error',\n                this.__onError._$bind(this,{\n                    code:_g._$CODE_ERRSERV,\n                    message:'无法加载指定资源文件['+this.__url+']！'\n                })\n            );\n        }\n        if (this.__timeout!=0){\n            _cache.timer = window.setTimeout(\n                this.__onError._$bind(this,{\n                    code:_g._$CODE_TIMEOUT,\n                    message:'指定资源文件['+this.__url+']载入超时！'\n                }),\n                this.__timeout||_timeout\n            );\n        }\n        if (!!_request){\n            this.__doRequest(_request);\n        }\n        this._$dispatchEvent('onloading');\n    };\n    /**\n     * 队列载入资源\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/loader/html.js'\n     * ],function(_t){\n     *     var _loader = _t._$$LoaderHtml._$allocate({\n     *         onload:function(){\n     *             // 载入队列资源成功的回调\n     *         }\n     *     });\n     *     // 路径列表，可以是绝对路径也可以是当前页面的相对路径\n     *     var _list = [\n     *         '../../../html/util/formTest.html',\n     *         '../../../html/util/cacheTest.html'\n     *     ];\n     *     _loader._$queue(_list);\n     * });\n     * ```\n     * \n     * @method module:util/ajax/loader/loader._$$LoaderAbstract#_$queue\n     * @param  {Array} arg0 - 资源地址队列\n     * @return {Void}\n     */\n    _pro._$queue = function(_list){\n        if (!_list||!_list.length){\n            this._$dispatchEvent('onerror',{\n                code:_g._$CODE_NOTASGN,\n                message:'请指定要载入的资源队列！'\n            });\n            return;\n        } \n        this.__key = _u._$uniqueID();\n        var _cache = {error:0,loaded:0,total:_list.length};\n        this.__setLoadData(this.__key,_cache);\n        _u._$forEach(\n            _list,function(v,i){\n                if (!v){\n                    _cache.total--;\n                    return;\n                }\n                this.__doLoadQueue(v);\n            },this\n        );\n        this._$dispatchEvent('onloading');\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/loader/platform/html.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/element'\n],function(_e,_p,_o,_f,_r){\n    /**\n     * 删除IFrame节点，保留历史\n     * @param  {Node} iframe节点\n     * @return {Void}\n     */\n    _p.__removeIFrameKeepHistory = function(_iframe){\n        _e._$remove(_iframe);\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/loader/platform/html.patch.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    './html.js',\n    'base/element',\n    'base/platform'\n],function(_h,_e,_m,_p,_o,_f,_r){\n    // for ie6-\n    NEJ.patch('TR<=2.0',function(){\n        /**\n         * 删除IFrame节点，保留历史\n         * @param  {Node} iframe节点\n         * @return {Void}\n         */\n        _h.__removeIFrameKeepHistory = function(_iframe){\n            _e._$setStyle(_iframe,'display','none');\n            try{_iframe.contentWindow.document.body.innerHTML = '&nbsp;';}catch(ex){}\n        };\n    });\n    \n    return _h;\n});\n"
  },
  {
    "path": "src/util/ajax/loader/script.js",
    "content": "/*\n * ------------------------------------------\n * 脚本加载器实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/ajax/loader/script */\nNEJ.define([\n    './loader.js',\n    'base/klass',\n    'base/element'\n],function(_t,_k,_e,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 脚本加载器\n     * \n     * @class    module:util/ajax/loader/script._$$LoaderScript\n     * @extends  module:util/ajax/loader/loader._$$LoaderAbstract\n     * \n     * @param    {Object} config   - 可选配置参数\n     * @property {Boolean} async   - 异步载入并立刻执行，默认为!0\n     * @property {String}  charset - 脚本编码\n     */\n    _p._$$LoaderScript = _k._$klass();\n    _pro = _p._$$LoaderScript._$extend(_t._$$LoaderAbstract);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/ajax/loader/script._$$LoaderScript#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__async = _options.async;\n        this.__charset = _options.charset;\n        this.__qopt.async = !1;\n        this.__qopt.charset = this.__charset;\n    };\n    /**\n     * 取资源载入控件\n     * \n     * @protected\n     * @method module:util/ajax/loader/script._$$LoaderScript#__getRequest\n     * @return {Script} 控件\n     */\n    _pro.__getRequest = function(){\n        var _request = _e._$create('script');\n        if (this.__async!=null){\n            _request.async = !!this.__async;\n        }\n        if (this.__charset!=null){\n            _request.charset = this.__charset;\n        }\n        return _request;\n    };\n    /**\n     * 删除控件\n     * \n     * @protected\n     * @method module:util/ajax/loader/script._$$LoaderScript#__doClearRequest\n     * @param  {Node} arg0 - 控件节点\n     * @return {Void}\n     */\n    _pro.__doClearRequest = function(_request){\n        _e._$remove(_request);\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/loader/style.js",
    "content": "/*\n * ------------------------------------------\n * 样式加载器实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/ajax/loader/style */\nNEJ.define([\n    './loader.js',\n    'base/klass',\n    'base/element'\n],function(_t,_k,_e,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 样式加载器\n     *\n     * @class   module:util/ajax/loader/style._$$LoaderStyle\n     * @extends module:util/ajax/loader/loader._$$LoaderAbstract\n     *\n     * @param   {Object} config - 可选配置参数\n     */\n    _p._$$LoaderStyle = _k._$klass();\n    _pro = _p._$$LoaderStyle._$extend(_t._$$LoaderAbstract);\n    /**\n     * 取资源载入控件\n     *\n     * @protected\n     * @method module:util/ajax/loader/style._$$LoaderStyle#__getRequest\n     * @return {Node} 控件节点\n     */\n    _pro.__getRequest = function(){\n        return _e._$create('link');\n    };\n    /**\n     * 资源载入\n     *\n     * @protected\n     * @method module:util/ajax/loader/style._$$LoaderStyle#__doRequest\n     * @param  {Node} 控件节点\n     * @return {Void}\n     */\n    _pro.__doRequest = function(_request){\n        _request.href = this.__url;\n        document.head.appendChild(_request);\n    };\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/loader/test/loader.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>load测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit load test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <script src=\"../../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./loader.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/ajax/loader/test/loader.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"Load\");\n    \n    var _  = NEJ.P,\n        _p = _('nej.ut.j'),\n\t\t_j = _('nej.j');\n    \n    test('load HTML资源',function(){\n        stop();\n        var _htmlLoad = _p._$$LoaderHtml._$allocate({timeout:30000,\n              onloaded:function(){\n                ok(true,'载入HTML资源成功');\n                start();\n              }});\n        _htmlLoad._$load('../../../html/util/formTest.html');\n    });\n\t\n\ttest('load HTML资源，通过api',function(){\n        stop();\n\t\t_j._$loadHtml('../../../html/util/formTest.html',{\n              onloaded:function(){\n                ok(true,'载入HTML资源成功');\n                start();\n              }});\n    });\n    \n    test('load script资源',function(){\n        stop();\n        var _scriptLoad = _p._$$LoaderScript._$allocate({\n              onloaded:function(){\n                ok(true,'载入script资源成功');\n                start();\n              }});\n        _scriptLoad._$load('../../../javascript/log.js');\n    });\n\t\n\t test('load script资源，通过api',function(){\n        stop();\n        _j._$loadScript('../../../javascript/log.js',{\n              onloaded:function(){\n                ok(true,'载入script资源成功');\n                start();\n              }});\n    });\n\t\n    test('load style资源',function(){\n        stop();\n        var _styleLoad = _p._$$LoaderStyle._$allocate({\n              onloaded:function(){\n                ok(true,'载入style资源成功');\n                start();\n              }});\n        _styleLoad._$load('../../../base/qunit.css');\n    });\n\t\n\t test('load style资源，通过api',function(){\n        stop();\n        _j._$loadStyle('../../../base/qunit.css',{\n              onloaded:function(){\n                ok(true,'载入style资源成功');\n                start();\n              }});\n    });\n\t\n\ttest('载入队列资源',function(){\n\t\tstop();\n\t\tvar _list = ['../../../html/util/formTest.html','../../../html/util/cacheTest.html']\n        var _styleLoad = _p._$$LoaderHtml._$allocate({\n              onloaded:function(){\n                ok(true,'载入html资源队列成功');\n                start();\n              }});\n        _styleLoad._$queue(_list);\n\t});\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}loader.test.js',\n    ['{lib}util/ajax/tag.js',\n     '{lib}util/ajax/loader/html.js',\n     '{lib}util/ajax/loader/script.js',\n     '{lib}util/ajax/loader/style.js'],f);\n});\n  "
  },
  {
    "path": "src/util/ajax/loader/text.js",
    "content": "/*\n * ------------------------------------------\n * 文本资源加载器实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/ajax/loader/text */\nNEJ.define([\n    './loader.js',\n    'base/klass',\n    'base/element',\n    'util/ajax/xdr'\n],function(_t,_k,_e,_j,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 文本资源加载器\n     *\n     * @class   module:util/ajax/loader/text._$$LoaderText\n     * @extends module:util/ajax/loader/loader._$$LoaderAbstract\n     *\n     * @param   {Object} config - 可选配置参数\n     */\n    _p._$$LoaderText = _k._$klass();\n    _pro = _p._$$LoaderText._$extend(_t._$$LoaderAbstract);\n    /**\n     * 取资源载入控件\n     *\n     * @protected\n     * @method module:util/ajax/loader/style._$$LoaderText#__getRequest\n     * @return {Node} 控件节点\n     */\n    _pro.__getRequest = function(){\n        this.__doRequest();\n        return null;\n    };\n    /**\n     * 执行清理任务\n     *\n     * @protected\n     * @method module:util/ajax/loader/style._$$LoaderText#__doClear\n     * @return {Void}\n     */\n    _pro.__doClear = function(){\n        this.__super();\n        this.__getLoadData('loaded')[this.__url] = !1;\n    };\n    /**\n     * 资源载入\n     *\n     * @protected\n     * @method module:util/ajax/loader/style._$$LoaderText#__doRequest\n     * @param  {Node} 控件节点\n     * @return {Void}\n     */\n    _pro.__doRequest = function(){\n        _j._$request(this.__url,{\n            method:'GET',\n            type:'text',\n            onload:this.__onLoaded._$bind(this),\n            onerror:this.__onError._$bind(this)\n        });\n    };\n    /**\n     * 资源载入成功事件\n     *\n     * @protected\n     * @method module:util/ajax/loader/style._$$LoaderText#__onLoaded\n     * @return {Void}\n     */\n    _pro.__onLoaded = function(_text){\n        this.__doCallback('onload',{\n            url:this.__url,\n            content:_text\n        });\n    };\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/message.js",
    "content": "/*\n * ------------------------------------------\n * 跨文档消息交互API实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/ajax/message */\nNEJ.define([\n    'base/global',\n    'base/util',\n    'base/element',\n    '{platform}message.js'\n],function(NEJ,_u,_e,_h,_p,_o,_f,_r){\n    /**\n     * 发送跨文档的消息\n     *\n     * 结构举例\n     * ```html\n     * <!-- 注意需要通过source进行双向交互的frame节点必须设置id属性作为标识 -->\n     * <iframe id=\"targetFrame\" src=\"http://a.b.com/a.html\"></iframe>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/event'\n     *     'util/ajax/message'\n     * ],function(_v,_j){\n     *     // top页面代码\n     *     // 发送消息至 http://c.d.com 的页面\n     *     _j._$postMessage('targetFrame',{\n     *         data:'hello c.d.com',\n     *         origin:'http://c.d.com'\n     *     });\n     *\n     *     // http://a.b.com/a.html页面代码\n     *     // 添加消息监测事件\n     *     _v._$addEvent(\n     *         window,'message',function(_event){\n     *             // 因为top页面发送消息到 http://c.d.com\n     *             // 所以在http://a.b.com页面不会收到任何消息\n     *         }\n     *     );\n     *\n     *     // top页面代码\n     *     // 发送消息至 http://a.b.com 的页面\n     *     _j._$postMessage('targetFrame',{\n     *         data:'hello a.b.com'\n     *     });\n     *\n     *     // http://a.b.com/a.html页面代码\n     *     // 添加消息监测事件\n     *     _v._$addEvent(\n     *         window,'message',function(_event){\n     *             // 必须先验证消息来源_event.origin是否你允许的域\n     *              if (!_isAllow(_event.origin))\n     *                 return;\n     *\n     *             // 处理_event.data中的消息内容\n     *             // TODO something\n     *\n     *             // 回复消息，使用_event.source\n     *             _j._$postMessage(_event.source,{\n     *                 data:'hello!',\n     *                 origin:_event.origin\n     *             });\n     *         }\n     *     );\n     * });\n     * ```\n     *\n     * @method module:util/ajax/message._$postMessage\n     * @param  {String|Window} arg0   - window对象或者Frame的name，或者字符串如_top、_parent、_self\n     * @param  {Object}        arg1   - 消息配置\n     * @property {Variable}      data   - 消息内容\n     * @property {String}        origin - 目标Origin，只有指定的页面可以收到消息，如http://a.b.com\n     * @property {String}        source - 当前窗体标识，除非你非常确定当前窗体的标识是什么，否则请采用自动识别\n     * @return {Void}\n     */\n    _p._$postMessage = (function(){\n        var _self = window.name||'_parent',\n            _wmap = {\n                '_top'   : window.top,\n                '_self'  : window,\n                '_parent': window.parent\n            };\n        return function(_target,_options){\n            if (_u._$isString(_target)){\n                _target = _wmap[_target]||\n                          window.frames[_target]||\n                         (_e._$get(_target)||_o).contentWindow;\n                if (!_target) return;\n            }\n            // check data\n            var _data = _u._$fetch({\n                data:null,\n                origin:'*',\n                source:_self\n            },_options);\n            // send message\n            _h.__postMessage(_target,_data);\n        };\n    })();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.j'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/platform/message.js",
    "content": "/*\n * ------------------------------------------\n * 跨文档消息交互API实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define(function(_p,_o,_f,_r){\n    /**\n     * 格式化源信息\n     * @param  {String} 源\n     * @return {String} 格式化后源\n     */\n    _p.__formatOrigin = (function(){\n        var _reg = /^([\\w]+?:\\/\\/.*?(?=\\/|$))/i;\n        return function(_origin){\n            _origin = _origin||'';\n            if (_reg.test(_origin)){\n                return RegExp.$1;\n            }\n            return '*';\n        };\n    })();\n    /**\n     * 解析消息传递数据\n     * @param  {Variable} 数据\n     * @return {Variable} 数据\n     */\n    _p.__formatPassData = function(_data){\n        return _data;\n    };\n    /**\n     * 跨文档发送数据\n     * @param  {Window} 窗体对象\n     * @param  {Object} 发送配置\n     * @return {Void}\n     */\n    _p.__postMessage = function(_window,_options){\n        if (!_window.postMessage){\n            return;\n        }\n        _options = _options||_o;\n        _window.postMessage(\n            _p.__formatPassData(_options.data),\n            _p.__formatOrigin(_options.origin)\n        );\n    };\n    \n    return _p;\n});"
  },
  {
    "path": "src/util/ajax/platform/message.patch.js",
    "content": "/*\n * ------------------------------------------\n * 跨文档消息交互API实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    './message.js',\n    'base/util',\n    'base/event'\n],function(_h,_u,_v,_p,_o,_f,_r){\n    // for ie8-9\n    NEJ.patch('4.0<=TR<=5.0',function(){\n        /**\n         * 解析消息传递数据\n         * @param  {Variable} 数据\n         * @return {Variable} 数据\n         */\n        _h.__formatPassData = function(_data){\n            // ie8-9 only support string data\n            return JSON.stringify(_data);\n        };\n    });\n    // for ie7-\n    NEJ.patch('TR<=3.0',[\n        'util/event/event',\n        'util/encode/json'\n    ],function(_t){\n        var _key = 'MSG|',\n            _queue = [];\n        /*\n         * 检测window.name变化情况\n         * @return {Void}\n         */\n        var _doCheckWindowName = function(){\n            // check name\n            var _name = unescape(window.name||'').trim();\n            if (!_name||_name.indexOf(_key)!=0) return;\n            window.name = '';\n            // check result\n            var _result = _u._$string2object(_name.replace(_key,''),'|'),\n                _origin = (_result.origin||'').toLowerCase();\n            // check origin\n            if (!!_origin&&_origin!='*'&&\n                location.href.toLowerCase().indexOf(_origin)!=0){\n                return;\n            }\n            // dispatch onmessage event\n            _v._$dispatchEvent(window,'message',{\n                data:JSON.parse(_result.data||'null'),\n                source:window.frames[_result.self]||_result.self,\n                origin:_h.__formatOrigin(_result.ref||document.referrer)\n            });\n        };\n        /*\n         * 检测window.name设置队列\n         * @return {Void}\n         */\n        var _doCheckNameQueue = (function(){\n            var _checklist;\n            // set window.name\n            var _doSetWindowName = function(_map,_index,_list){\n                if (_u._$indexOf(_checklist,_map.w)<0){\n                    _checklist.push(_map.w);\n                    _list.splice(_index,1);\n                    _map.w.name = _map.d;\n                }\n            };\n            return function(){\n                _checklist = [];\n                _u._$reverseEach(_queue,_doSetWindowName);\n                _checklist = null;\n            };\n        })();\n        /**\n         * 跨文档发送数据\n         * @param  {Window} 窗体对象\n         * @param  {Object} 发送配置\n         * @return {Void}\n         */\n        _h.__postMessage = (function(){\n            // serialize send data\n            var _doSerialize = function(_data){\n                var _result = {};\n                _data = _data||_o;\n                _result.origin = _data.origin||'';\n                _result.ref  = location.href;\n                _result.self = _data.source;\n                _result.data = JSON.stringify(_data.data);\n                return _key+_u._$object2string(_result,'|',!0);\n            };\n            // function body\n            return function(_window,_options){\n                _queue.unshift({\n                    w:_window,\n                    d:escape(_doSerialize(_options))\n                });\n            };\n        })();\n\n        // init window onmessage event\n        _t._$$CustomEvent._$allocate({\n            element:window,\n            event:'message'\n        });\n        setInterval(_doCheckNameQueue,100);\n        setInterval(_doCheckWindowName,20);\n    });\n\n    return _h;\n});\n"
  },
  {
    "path": "src/util/ajax/platform/xdr.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    '../proxy/xhr.js',\n    '../proxy/flash.js',\n    '../proxy/frame.js',\n    '../proxy/upload.js'\n],function(_t0,_t1,_t2,_t3,_p,_o,_f,_r){\n    /**\n     * 根据模式返回代理实例，模式说明\n     * 0 - 自动模式，高版本使用HTML5的CORS协议，低版本采用Frame代理方式\n     * 1 - 高版本使用HTML5的CORS协议，普通请求低版本采用Flash代理方式\n     * 2 - 全部使用Frame代理方式\n     * 3 - 全部使用Flash代理方式\n     * @param  {Number}   模式\n     * @param  {Boolean}  是否文件上传\n     * @param  {Object}   构造配置参数\n     * @return {_$$ProxyAbstract} 代理实例\n     */\n    _p.__getProxyByMode = function(_mode,_upload,_options){\n        var _map = !!_upload \n                 ? {2:_t3._$$ProxyUpload}\n                 : {2:_t2._$$ProxyFrame,3:_t1._$$ProxyFlash};\n        return (_map[_mode]||_t0._$$ProxyXHR)._$allocate(_options);\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/platform/xdr.patch.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    './xdr.js'\n],function(_h,_p,_o,_f,_r){\n    // for ie9-\n    NEJ.patch('TR<=5.0',function(){\n        /**\n         * 根据模式返回代理实例，模式说明\n         * 0 - 自动模式，高版本使用HTML5的CORS协议，低版本采用Frame代理方式\n         * 1 - 高版本使用HTML5的CORS协议，普通请求低版本采用Flash代理方式\n         * 2 - 全部使用Frame代理方式\n         * 3 - 全部使用Flash代理方式\n         * @param  {Number}  模式\n         * @param  {Boolean} 是否文件上传\n         * @param  {Object}  构造配置参数\n         * @return {_$$ProxyAbstract} 代理实例\n         */\n        _h.__getProxyByMode = (function(){\n            var _pmap = {0:2,1:3};\n            return _h.__getProxyByMode._$aop(function(_event){\n               var _args = _event.args,\n                   _mode = _args[0]||0;\n               _args[0] = !!_args[1] ? 2 :\n                          _pmap[_mode]||_mode;\n            });\n        })();\n    });\n    \n    return _h;\n});\n"
  },
  {
    "path": "src/util/ajax/proxy/flash.js",
    "content": "/*\n * ------------------------------------------\n * Ajax FLASH方式代理实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/ajax/proxy/flash */\nNEJ.define([\n    './proxy.js',\n    'base/klass',\n    'base/config',\n    'base/util',\n    'util/flash/flash'\n],function(_t,_k,_c,_u,_e,_p,_o,_f,_r){\n    var _pro,\n        _cache = {},\n        _seed = _u._$uniqueID();\n    /*\n     * 代理请求正常回调\n     * @param  {String} 请求标识\n     * @param  {String} 返回数据\n     * @return {Void}\n     */\n    this['ld'+_seed] = function(_key,_text){\n        var _proxy = _cache[_key];\n        if (!_proxy) return;\n        delete _cache[_key];\n        _proxy.__onLoadRequest({\n            status:200,\n            result:_text\n        });\n    };\n    /*\n     * 代理请求异常回调\n     * @param  {String} 请求标识\n     * @param  {Number} 请求状态\n     * @return {Void} \n     */\n    this['er'+_seed] = function(_key,_status){\n        var _proxy = _cache[_key];\n        if (!_proxy) return;\n        delete _cache[_key];\n        _proxy.__onLoadRequest({\n            status:_status||0\n        });\n    };\n    /**\n     * Flash代理方式Ajax请求对象\n     * \n     * @class   module:util/ajax/proxy/flash._$$ProxyFlash\n     * @extends module:util/ajax/proxy/proxy._$$ProxyAbstract\n     * \n     * @param   {Object}  config - 构造配置参数\n     */\n    _p._$$ProxyFlash = _k._$klass();\n    _pro = _p._$$ProxyFlash._$extend(_t._$$ProxyAbstract);\n    /**\n     * 往服务器发送请求\n     * \n     * @protected\n     * @method module:util/ajax/proxy/flash._$$ProxyFlash#__doSendRequest\n     * @param  {Object} arg0 - 请求信息\n     * @return {Void}\n     */\n    _pro.__doSendRequest = function(_options){\n        var _flash = _cache.flash;\n        // callback list\n        if (_u._$isArray(_flash)){\n            _flash.push(\n                this.__doSendRequest.\n                    _$bind(this,_options)\n            );\n            return;\n        }\n        // build flash proxy\n        if (!_flash){\n            _cache.flash = [\n                this.__doSendRequest.\n                    _$bind(this,_options)\n            ];\n            _e._$flash({\n                hidden:!0,\n                src:_c._$get('ajax.swf'),\n                onready:function(_flash){\n                    if (!_flash) return;\n                    var _list = _cache.flash;\n                    _cache.flash = _flash;\n                    _u._$reverseEach(\n                        _list,function(_handler,_index,_list){\n                            try{\n                                _handler();\n                            }catch(ex){\n                                // ignore\n                            }\n                        }\n                    );\n                }\n            });\n            return;\n        }\n        // send request by flash\n        this.__rkey = _u._$uniqueID();\n        _cache[this.__rkey] = this;\n        var _data = _u._$fetch({\n            url:'',\n            data:null,\n            method:'GET'\n        },_options.request);\n        _data.key = this.__rkey;\n        _data.headers  = _options.headers;\n        _data.onerror  = 'cb.er'+_seed;\n        _data.onloaded = 'cb.ld'+_seed;\n        var _policy = _c._$getFlashProxy(_data.url);\n        if (!!_policy){\n            _data.policyURL = _policy;\n        }\n        _flash.request(_data);\n    };\n    /**\n     * 中断请求\n     * \n     * @method module:util/ajax/proxy/flash._$$ProxyFlash#_$abort\n     * @return {Void}\n     */\n    _pro._$abort = function(){\n        delete _cache[this.__rkey];\n        this.__onAbort();\n    };\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/proxy/frame.js",
    "content": "/*\n * ------------------------------------------\n * Ajax FRAME方式代理实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/ajax/proxy/frame */\nNEJ.define([\n    './proxy.js',\n    'base/util',\n    'base/klass',\n    'base/event',\n    'base/config',\n    'base/element',\n    'util/ajax/message'\n],function(_t,_u,_k,_v,_c,_e,_j,_p,_o,_f,_r){\n    var _pro,\n        _cache = {};\n    /**\n     * Frame代理方式Ajax请求对象\n     * \n     * @class   module:util/ajax/proxy/frame._$$ProxyFrame\n     * @extends module:util/ajax/proxy/proxy._$$ProxyAbstract\n     * \n     * @param   {Object}  config - 构造配置参数\n     */\n    _p._$$ProxyFrame = _k._$klass();\n    _pro = _p._$$ProxyFrame._$extend(_t._$$ProxyAbstract);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:util/ajax/proxy/frame._$$ProxyFrame#__init\n     * @return {Void}\n     */\n    _pro.__init = (function(){\n        var _flag = 'NEJ-AJAX-DATA:',\n            _init = !1;\n        // receive message\n        var _doReceiveMessage = function(_event){\n            var _data = _event.data;\n            if (_data.indexOf(_flag)!=0) return;\n            _data = JSON.parse(_data.replace(_flag,''));\n            var _proxy = _cache[_data.key];\n            if (!_proxy) return;\n            delete _cache[_data.key];\n            _data.result = decodeURIComponent(_data.result||'');\n            _proxy.__onLoadRequest(_data);\n        };\n        // init message listener\n        var _doInitMessage = function(){\n            if (!_init){\n                _init = !0;\n                _v._$addEvent(\n                    window,'message',\n                    _doReceiveMessage\n                );\n            }\n        };\n        return function(){\n            this.__super();\n            _doInitMessage();\n        };\n    })();\n    /**\n     * 往服务器发送请求\n     *\n     * @protected\n     * @method module:util/ajax/proxy/frame._$$ProxyFrame#__doSendRequest\n     * @param  {Object} arg0 - 请求信息\n     * @return {Void}\n     */\n    _pro.__doSendRequest = function(_options){\n        var _request = _options.request,\n            _proxy = _c._$getFrameProxy(_request.url),\n            _frame = _cache[_proxy];\n        // callback list\n        if (_u._$isArray(_frame)){\n            _frame.push(\n                this.__doSendRequest.\n                    _$bind(this,_options)\n            );\n            return;\n        }\n        // build frame proxy\n        if (!_frame){\n            _cache[_proxy] = [\n                this.__doSendRequest.\n                    _$bind(this,_options)\n            ];\n            _e._$createXFrame({\n                src:_proxy,visible:!1,\n                onload:function(_event){\n                    var _list = _cache[_proxy];\n                    _cache[_proxy] = _v.\n                        _$getElement(_event).contentWindow;\n                    _u._$reverseEach(\n                        _list,function(_handler){\n                            try{\n                                _handler();\n                            }catch(ex){\n                                // ignore\n                            }\n                        }\n                    );\n                }\n            });\n            return;\n        }\n        // send message to frame\n        this.__rkey = _u._$uniqueID();\n        _cache[this.__rkey] = this;\n        var _data = _u._$fetch({\n            url:'',data:null,\n            timeout:0,method:'GET'\n        },_request);\n        _data.key = this.__rkey;\n        _data.headers = _options.headers;\n        _j._$postMessage(_cache[_proxy],{data:_data});\n    };\n    /**\n     * 中断请求\n     * \n     * @method module:util/ajax/proxy/frame._$$ProxyFrame#_$abort\n     * @return {Void}\n     */\n    _pro._$abort = function(){\n        delete _cache[this.__rkey];\n        this.__onAbort();\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/proxy/platform/xhr.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define(function(_p,_o,_f,_r){\n    /**\n     * 取XHR对象\n     * @return {XMLHttpRequest} XHR对象\n     */\n    _p.__getXMLHttpRequest = function(){\n        return new XMLHttpRequest();\n    };\n    /**\n     * 判断是否有Abort事件\n     * @return {Boolean}\n     */\n    _p.__hasAbortEvent = function(){\n        return !0;\n    };\n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/proxy/platform/xhr.patch.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    './xhr.js',\n    'base/util'\n],function(_h,_u,_p,_o,_f,_r){\n    // for ie9-\n    NEJ.patch('TR<=5.0',function(){\n        /**\n         * 判断是否有Abort事件\n         * @return {Boolean}\n         */\n        _h.__hasAbortEvent = function(){\n            return !1;\n        };\n    });\n    // for ie6-\n    NEJ.patch('TR<=2.0',function(){\n        /**\n         * 取XHR对象\n         * @return {XMLHttpRequest} XHR对象\n         */\n        _h.__getXMLHttpRequest = (function(){\n            // http://blogs.msdn.com/b/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx\n            var _msxml = [\n                'Msxml2.XMLHTTP.6.0',\n                'Msxml2.XMLHTTP.3.0',\n                'Msxml2.XMLHTTP.4.0',\n                'Msxml2.XMLHTTP.5.0',\n                'MSXML2.XMLHTTP',\n                'Microsoft.XMLHTTP'\n            ];\n            return function(){\n                var _xhr = null;\n                _u._$forIn(\n                    _msxml,function(_name){\n                        try{\n                            _xhr = new ActiveXObject(_name);\n                            return !0;\n                        }catch(e){\n                            // ignore exception\n                        }\n                    }\n                );\n                return _xhr;\n            };\n        })();\n    });\n\n    return _h;\n});\n"
  },
  {
    "path": "src/util/ajax/proxy/proxy.js",
    "content": "/*\n * ------------------------------------------\n * Ajax代理实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/ajax/proxy/proxy */\nNEJ.define([\n    'base/klass',\n    'base/util',\n    'base/element',\n    'base/config',\n    'base/constant',\n    'util/event',\n    'util/cache/cookie',\n    'util/encode/json'\n],function(_k,_u,_e,_c,_g,_t,_j,JSON,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * Ajax代理对象\n     * \n     * @class   module:util/ajax/proxy/proxy._$$ProxyAbstract\n     * @extends module:util/event._$$EventTarget\n     * \n     * @param    {Object}  config  - 构造配置参数\n     * @property {String}  url     - 请求地址\n     * @property {Boolean} sync    - 是否同步请求\n     * @property {String}  type    - 返回数据格式,text/json/xml\n     * @property {String}  method  - 请求方式,GET/POST\n     * @property {Number}  timeout - 超时时间,0表示禁止超时监测\n     * @property {Object}  headers - 头信息\n     */\n    /** \n     * 载入回调\n     * \n     * @event module:util/ajax/proxy/proxy._$$ProxyAbstract#onload\n     * @param {Object} event - 服务器返回数据信息\n     */\n    /** \n     * 异常回调\n     * \n     * @event    module:util/ajax/proxy/proxy._$$ProxyAbstract#onerror\n     * @param    {Object}   event   - 错误信息\n     * @property {Number}   code    - 错误代码\n     * @property {String}   message - 错误描述\n     * @property {Variable} data    - 出错时携带数据\n     */\n    /** \n     * [hr]\n     * 请求之前对数据处理回调\n     * @event    module:util/ajax/proxy/proxy._$$ProxyAbstract#onbeforerequest\n     * @param    {Object} event   - 请求信息\n     * @property {Object} request - 请求参数，数据信息 url/sync/cookie/type/method/timeout\n     * @property {Object} headers - 请求头信息\n     */\n    _p._$$ProxyAbstract = _k._$klass();\n    _pro = _p._$$ProxyAbstract._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/ajax/proxy/proxy._$$ProxyAbstract#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        // reset request information\n        this.__request = _u._$fetch({\n            url:'',\n            sync:!1,\n            cookie:!1,\n            type:'text',\n            method:'GET',\n            timeout:60000\n        },_options);\n        // for csrf attack\n        var _csrf = _c._$get('csrf');\n        if (!!_csrf.cookie&&!!_csrf.param){\n            var _query = encodeURIComponent(_csrf.param)+'='+\n                         encodeURIComponent(_j._$cookie(_csrf.cookie)||''),\n                _split = this.__request.url.indexOf('?')<0?'?':'&';\n            this.__request.url += _split+_query;\n        }\n        // reset headers\n        this.__headers = _options.headers||{};\n        var _content = this.__headers[_g._$HEAD_CT];\n        if (_content==null){\n            this.__headers[_g._$HEAD_CT] = _g._$HEAD_CT_FORM;\n        }\n    };\n    /**\n     * 回收控件\n     * \n     * @protected\n     * @method module:util/ajax/proxy/proxy._$$ProxyAbstract#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__rkey;\n        delete this.__request;\n        delete this.__headers;\n    };\n    /**\n     * 请求载入回调\n     * \n     * @protected\n     * @method   module:util/ajax/proxy/proxy._$$ProxyAbstract#__onLoadRequest\n     * @param    {Object} arg0   - 数据信息\n     * @property {Number} status - 请求状态\n     * @property {String} result - 请求结果，纯文本形式\n     * @return   {Void}\n     */\n    _pro.__onLoadRequest = function(_event){\n        var _status = _event.status;\n        // timeout error\n        if (_status==-1){\n            this._$dispatchEvent('onerror',{\n                code:_g._$CODE_TIMEOUT,\n                message:'请求['+this.__request.url+']超时！'\n            });\n            return;\n        }\n        // check status\n        if ((''+_status).indexOf('2')!=0){\n            this._$dispatchEvent('onerror',{\n                data:_status,\n                result:_event.result,\n                code:_g._$CODE_ERRSERV,\n                message:'服务器返回异常状态['+_status+']!'\n            });\n            return;\n        }\n        // onload\n        this._$dispatchEvent(\n             'onload',_e._$text2type(\n                 _event.result,\n                 this.__request.type\n             )\n        );\n    };\n    /**\n     * 往服务器发送请求，子类实现具体业务逻辑\n     * \n     * @abstract\n     * @method module:util/ajax/proxy/proxy._$$ProxyAbstract#__doSendRequest\n     * @param  {Object} arg0 - 请求信息\n     * @return {Void}\n     */\n    _pro.__doSendRequest = _f;\n    /**\n     * 取头信息，子类实现具体业务逻辑\n     * \n     * @abstract\n     * @method module:util/ajax/proxy/proxy._$$ProxyAbstract#__getResponseHeader\n     * @param  {String} arg0 - 要取的头信息名称\n     * @return {String}        头信息结果或集合\n     */\n    _pro.__getResponseHeader = _f;\n    /**\n     * 请求终止事件\n     * @private\n     */\n    _pro.__onAbort = function(){\n        this._$dispatchEvent('onerror',{\n            code:_g._$CODE_ERRABRT,\n            message:'客户端终止请求'\n        });\n    };\n    /**\n     * 发送请求\n     * \n     * @method module:util/ajax/proxy/proxy._$$ProxyAbstract#_$send\n     * @param  {Variable} arg0 - 要发送的数据\n     * @return {Void}\n     */\n    _pro._$send = function(_data){\n        var _url = this.__request.url;\n        if (!_url){\n            this._$dispatchEvent('onerror',{\n                code:_g._$CODE_NOTASGN,\n                message:'没有输入请求地址！'\n            });\n            return;\n        }\n        try{\n            this.__request.data = _data==null?null:_data;\n            var _event = {\n                request:this.__request,\n                headers:this.__headers\n            };\n            // adjust param before request\n            try{\n                this._$dispatchEvent('onbeforerequest',_event);\n            }catch(ex){\n                // ignore exception\n                console.error(ex.message);\n                console.error(ex.stack);\n            }\n            this.__doSendRequest(_event);\n        }catch(e){\n            this._$dispatchEvent('onerror',{\n                code:_g._$CODE_ERRSERV,\n                message:'请求['+_url+']失败:'+e.message+'！'\n            });\n        }\n    };\n    /**\n     * 中断请求，子类实现具体业务逻辑\n     *\n     * @abstract\n     * @method module:util/ajax/proxy/proxy._$$ProxyAbstract#_$abort\n     * @return {Void}\n     */\n    _pro._$abort = _f;\n    /**\n     * 取头信息\n     * \n     * @method module:util/ajax/proxy/proxy._$$ProxyAbstract#_$header\n     * @param  {String|Array}  arg0 - 要取的头信息名称\n     * @return {String|Object}        头信息结果或集合\n     */\n    _pro._$header = function(_key){\n        if (!_u._$isArray(_key)){\n            return this.__getResponseHeader(_key)||'';\n        }\n        var _result = {};\n        _u._$forEach(\n            _key,function(_value){\n                _result[_value] = this._$header(_value);\n            },this\n        );\n        return _result;\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/proxy/upload.js",
    "content": "﻿/*\n * ------------------------------------------\n * 文件上传代理实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/ajax/proxy/upload */\nNEJ.define([\n    './proxy.js',\n    'base/klass',\n    'base/util',\n    'base/event',\n    'base/element',\n    'base/constant',\n    'util/ajax/xdr',\n    'util/ajax/message'\n],function(_t,_k,_u,_v,_e,_g,_j0,_j1,_p,_o,_f,_r){\n    var _pro,\n        _cache = {},\n        _xflag = 'NEJ-UPLOAD-RESULT:';\n    /**\n     * 文件上传代理\n     *\n     * @class   module:util/ajax/proxy/upload._$$ProxyUpload\n     * @extends module:util/ajax/proxy/proxy._$$ProxyAbstract\n     *\n     * @param   {Object}  config - 构造配置参数\n     */\n    _p._$$ProxyUpload = _k._$klass();\n    _pro = _p._$$ProxyUpload._$extend(_t._$$ProxyAbstract);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:util/ajax/proxy/upload._$$ProxyUpload#__init\n     * @return {Void}\n     */\n    _pro.__init = (function(){\n        var _init = !1;\n        // receive message callback\n        var _doReceiveMessage = function(_event){\n            var _data = _event.data;\n            if (_data.indexOf(_xflag)!=0) return;\n            _data = JSON.parse(_data.replace(_xflag,''));\n            var _proxy = _cache[_data.key];\n            if (!_proxy) return;\n            delete _cache[_data.key];\n            _proxy.__onLoadRequest(\n                decodeURIComponent(_data.result)\n            );\n        };\n        // init message listener\n        var _doInitMessage = function(){\n            if (!_init){\n                _init = !0;\n                _v._$addEvent(\n                    window,'message',\n                    _doReceiveMessage\n                );\n            }\n        };\n        return function(){\n            this.__super();\n            _doInitMessage();\n        };\n    })();\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/ajax/proxy/upload._$$ProxyUpload#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        _e._$remove(this.__frame);\n        delete this.__frame;\n        window.clearTimeout(this.__timer);\n        delete this.__timer;\n    };\n    /**\n     * 请求载入回调\n     * \n     * @protected\n     * @method module:util/ajax/proxy/upload._$$ProxyUpload#__onLoadRequest\n     * @param  {String} arg0 - 数据信息\n     * @return {Void}\n     */\n    _pro.__onLoadRequest = function(_text){\n        try{\n            var _ret = _e._$text2type(\n                _text,this.__request.type\n            );\n            this._$dispatchEvent('onload',_ret);\n        }catch(ex){\n            this._$dispatchEvent('onerror',{\n                code:_g._$CODE_ERREVAL,\n                message:_text\n            });\n        }\n    };\n    /**\n     * 往服务器发送请求\n     * \n     * @protected\n     * @method module:util/ajax/proxy/upload._$$ProxyUpload#__doSendRequest\n     * @param  {Object} arg0 - 请求信息\n     * @return {Void}\n     */\n    _pro.__doSendRequest = (function(){\n        // same domain upload result check\n        var _doCheckResult = function(){\n            var _body,_text;\n            try{\n                var _body = this.__frame.contentWindow.document.body,\n                    _text = (_body.innerText||_body.textContent||'').trim();\n                // check result for same domain with upload proxy html\n                if (_text.indexOf(_xflag)>=0||\n                    _body.innerHTML.indexOf(_xflag)>=0){\n                    // use post message path\n                    return;\n                }\n            }catch(ex){\n                // ignore if not same domain\n                return;\n            }\n            this.__onLoadRequest(_text);\n        };\n        // check upload progress\n        var _doProgress = function(_url,_mode,_cookie){\n            _j0._$request(_url,{\n                type:'json',\n                method:'POST',\n                cookie:_cookie,\n                mode:parseInt(_mode)||0,\n                onload:function(_data){\n                    if (!this.__timer) return;\n                    this._$dispatchEvent('onuploading',_data);\n                    this.__timer = window.setTimeout(\n                        _doProgress._$bind(\n                            this,_url,_mode,_cookie\n                        ),1000\n                    );\n                }._$bind(this),\n                onerror:function(_error){\n                    if (!this.__timer) return;\n                    this.__timer = window.setTimeout(\n                        _doProgress._$bind(\n                            this,_url,_mode,_cookie\n                        ),1000\n                    );\n                }._$bind(this)\n            });\n        };\n        return function(_options){\n            var _request = _options.request,\n                _headers = _options.headers,\n                _form = _request.data,\n                _name = _u._$uniqueID();\n            _cache[_name]  = this;\n            _form.target   = _name;\n            _form.method   = 'POST';\n            _form.enctype  = _g._$HEAD_CT_FILE;\n            _form.encoding = _g._$HEAD_CT_FILE;\n            var _url = _form.action||'',\n                _sep = _url.indexOf('?')<=0?'?':'&';\n            _form.action = _url+_sep+'_proxy_=form';\n            this.__frame = _e._$createXFrame({\n                name:_name,\n                onload:function(_event){\n                    var _frame = _v._$getElement(_event);\n                    _v._$addEvent(\n                        _frame,'load',\n                        _doCheckResult._$bind(this)\n                    );\n                    _form.submit();\n                    var _qurl = (_form.nej_query||_o).value;\n                    if (!_qurl) return;\n                    var _mode = (_form.nej_mode||_o).value,\n                        _cookie = (_form.nej_cookie||_o).value==='true';\n                    this.__timer = window.setTimeout(\n                        _doProgress._$bind(\n                            this,_qurl,_mode,_cookie\n                        ),100\n                    );\n                }._$bind(this)\n            });\n        };\n    })();\n    /**\n     * 中断请求\n     * \n     * @method module:util/ajax/proxy/upload._$$ProxyUpload#_$abort\n     * @return {Void}\n     */\n    _pro._$abort = function(){\n        this.__onAbort();\n    };\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/proxy/xhr.js",
    "content": "/*\n * ------------------------------------------\n * XHR方式Ajax代理实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/ajax/proxy/xhr */\nNEJ.define([\n    './proxy.js',\n    'base/util',\n    'base/klass',\n    'base/constant',\n    '{platform}xhr.js'\n],function(_t,_u,_k,_g,_h,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * Ajax代理对象\n     * \n     * @class   module:util/ajax/proxy/xhr._$$ProxyXHR\n     * @extends module:util/ajax/proxy/proxy._$$ProxyAbstract\n     * \n     * @param   {Object} config - 构造配置参数\n     */\n    _p._$$ProxyXHR = _k._$klass();\n    _pro = _p._$$ProxyXHR._$extend(_t._$$ProxyAbstract);\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/ajax/proxy/xhr._$$ProxyXHR#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        // clear timeout\n        window.clearTimeout(this.__timer);\n        delete this.__timer;\n        // clear request\n        try{\n            this.__xhr.onreadystatechange = _f;\n            this.__xhr.abort();\n        }catch(e){\n            // ignore\n        }\n        delete this.__xhr;\n    };\n    /**\n     * 往服务器发送请求\n     * \n     * @protected\n     * @method module:util/ajax/proxy/xhr._$$ProxyXHR#__doSendRequest\n     * @param  {Object} arg0 - 请求信息\n     * @return {Void}\n     */\n    _pro.__doSendRequest = (function(){\n        // set header\n        var _doSetHeader = function(_value,_key){\n            this.__xhr.setRequestHeader(_key,_value);\n        };\n        // split input.file for multiple files\n        var _doSplitMultFiles = function(_form){\n            var _result = [];\n            _u._$reverseEach(\n                _form.getElementsByTagName('input'),\n                function(_input){\n                    if (_input.type!='file'){\n                        return;\n                    }\n                    // remove file without name\n                    if (!_input.name){\n                        _input.parentNode.removeChild(_input);\n                        return;\n                    }\n                    // for multiple file per-input\n                    if (_input.files.length>1){\n                        _u._$forEach(_input.files,function(_file){\n                            _result.push({name:_input.name,file:_file});\n                        });\n                        _input.parentNode.removeChild(_input);\n                    }\n                }\n            );\n            return _result.length>0?_result:null;\n        };\n        return function(_options){\n            var _request = _options.request,\n                _headers = _options.headers;\n            this.__xhr = _h.__getXMLHttpRequest();\n            // add event listener\n            // upload progress\n            if (_headers[_g._$HEAD_CT]===_g._$HEAD_CT_FILE){\n                delete _headers[_g._$HEAD_CT];\n                this.__xhr.upload.onprogress = \n                    this.__onStateChange._$bind(this,1);\n                if (_request.data.tagName==='FORM'){\n                    var _files = _doSplitMultFiles(_request.data);\n                    _request.data = new FormData(_request.data);\n                    _u._$forEach(_files,function(_ret){\n                        var _file = _ret.file;\n                        _request.data.append(\n                            _ret.name||_file.name||\n                            ('file-'+_u._$uniqueID()),_file\n                        );\n                    });\n                }\n            }\n            // state change\n            this.__xhr.onreadystatechange = \n                this.__onStateChange._$bind(this,2);\n            this.__xhr.onabort =\n                this.__onAbort._$bind(this);\n            // timeout\n            if (_request.timeout!==0){\n                this.__timer = window.setTimeout(\n                    this.__onStateChange._$bind(this,3),\n                    _request.timeout\n                );\n            }\n            // prepare and send request\n            this.__xhr.open(\n                _request.method,\n                _request.url,\n               !_request.sync\n            );\n            _u._$loop(_headers,_doSetHeader,this);\n            // support credential\n            if (!!this.__request.cookie&&\n               ('withCredentials' in this.__xhr)){\n                this.__xhr.withCredentials = !0;\n            }\n            // format data for sending Object\n            if(_headers[_g._$HEAD_CT]===_g._$HEAD_CT_FORM&&\n              (!window.FormData||!(_request.data instanceof window.FormData))){\n                if (_u._$isObject(_request.data)){\n                    _request.data = _u._$object2string(_request.data,'&',!0);\n                }\n            }\n            this.__xhr.send(_request.data);\n        };\n    })();\n    /**\n     * 请求状态变化事件\n     * \n     * @protected\n     * @method module:util/ajax/proxy/xhr._$$ProxyXHR#__onStateChange\n     * @param  {Number} arg0 - 状态变化类型\n     * @return {Void}\n     */\n    _pro.__onStateChange = function(_type){\n        switch(_type){\n            // upload progress\n            case 1 :\n                this._$dispatchEvent('onuploading',arguments[1]);\n            break;\n            // state change\n            case 2 :\n                if (this.__xhr.readyState==4){\n                    this.__onLoadRequest({\n                        status:this.__xhr.status,\n                        result:this.__xhr.responseText||''\n                    });\n                }\n            break;\n            // timeout\n            case 3:\n                this.__onLoadRequest({status:-1});\n            break;\n        }\n    };\n    /**\n     * 取头信息\n     * \n     * @protected\n     * @method module:util/ajax/proxy/xhr._$$ProxyXHR#__getResponseHeader\n     * @param  {String} arg0 - 要取的头信息名称\n     * @return {String}        头信息结果或集合\n     */\n    _pro.__getResponseHeader = function(_key){\n        return !this.__xhr?'':this.__xhr.getResponseHeader(_key);\n    };\n    /**\n     * 中断请求\n     * \n     * @method module:util/ajax/proxy/xhr._$$ProxyXHR#_$abort\n     * @return {Void}\n     */\n    _pro._$abort = function(){\n        if (!_h.__hasAbortEvent()){\n            this.__onAbort();\n        }else{\n            this.__xhr.onreadystatechange = _f;\n            this.__xhr.abort();\n        }\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/rest.js",
    "content": "/*\n * ------------------------------------------\n * REST交互接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/ajax/rest */\nNEJ.define([\n    'base/global',\n    'base/event',\n    'base/util',\n    'base/constant',\n    'util/ajax/xdr',\n    'util/event/event'\n],function(NEJ,_v,_u,_g,_j,_t,_p,_o,_f,_r){\n    /**\n     * 使用REST进行数据交互接口\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/event',\n     *     'util/ajax/rest'\n     * ],function(_v,_j){\n     *     // 通用错误处理，所有请求异常均会调用此回调处理\n     *     _v._$addEvent(\n     *         window,'resterror',function(_error){\n     *             // _error.code\n     *             // _error.message\n     *             // _error.data\n     *             // 通过设置_error.stopped阻止事件回调到请求的onerror中\n     *         }\n     *     );\n     *\n     *     var url = \"http://a.b.com/rest/list\";\n     *     var opt = {\n     *          param:{brand:'nokia',model:'9'},\n     *          data:'123',\n     *          method:'post',\n     *          onload:function(_data){\n     *              // 请求正常回调\n     *          },\n     *          onerror:function(_error){\n     *              // _error.code\n     *              // _error.message\n     *              // _error.data\n     *              // 如果window的resterror回调中stopped了事件则不会进入此回调\n     *          },\n     *          onbeforerequest:function(_event){\n     *              // _event.request\n     *              // _event.headers\n     *          }\n     *     }\n     *     _j._$request(url,opt);\n     * });\n     * ```\n     *\n     * @method module:util/ajax/rest._$request\n     * @param    {String}  arg0 - 请求地址\n     * @param    {Object}  arg1 - 可选配置参数\n     * @property {Boolean}  sync    - 是否同步请求\n     * @property {Variable} data    - 要发送的数据\n     * @property {Object}   param   - 请求参数,包括模板地址里使用的参数\n     * @property {String}   method  - 请求方式,GET/POST/PUT/DELETE\n     * @property {Number}   timeout - 超时时间,0 禁止超时监测\n     * @property {Object}   headers - 头信息，标准HTTP头字段\n     * @property {Object}   result  - onload回调输入时需包含的额外信息\n     *\n     * @property {module:util/ajax/xdr.onload} onload   - 请求载入成功回调\n     * @property {module:util/ajax/xdr.onerror} onerror - 请求载入失败回调\n     * @property {module:util/ajax/xdr.onbeforerequest} onbeforerequest - 发起请求之前回调\n     *\n     * @return   {String} 请求标识\n     */\n    _p._$request = (function(){\n        var _cache = {},  // request cache - sn:{s:funciton(){},f:function(){}}\n            _reg0 = /\\{(.*?)\\}/gi, // /api/{appid}/question/{id}\n            _reg2 = /\\/:([\\w]+?)(?=\\/|$)/gi, // /api/:appid/question/:id\n            _reg1 = /^get|delete|head$/i,\n            _jsn = /json/i,\n            _xml = /xml/i;\n        // clear request\n        var _doClear = function(_key){\n            var _request = _cache[_key];\n            if (!_request) return;\n            delete _request.s;\n            delete _request.f;\n            delete _cache[_key];\n        };\n        // request callback\n        var _doCallback = function(_key,_type){\n            var _request = _cache[_key];\n            if (!_request) return;\n            var _callback = _request[_type],\n                _args = _r.slice.call(arguments,2);\n            try{\n                (_callback||_f).apply(null,_args);\n            }catch(ex){\n                // ignore\n                if (DEBUG) throw ex;\n                console.error(ex.message);\n                console.error(ex);\n            }\n            _doClear(_key);\n        };\n        // request success\n        var _onLoad = function(_key,_data){\n            _doCallback(_key,'s',_data);\n        };\n        // request error\n        var _onError = function(_key,_error){\n            _error = _error||{};\n            // status 204 is ok\n            if (_error.code==_g._$CODE_ERRSERV&&\n                _error.data==204){\n                _onLoad(_key,null);\n                return;\n            }\n            // do error filter\n            // set error attr stopped=!0 will stop request error callback\n            _v._$dispatchEvent(\n                window,'resterror',_error\n            );\n            if (!!_error.stopped){\n                _doClear(_key);\n                return;\n            }\n            // do request fail callback\n            _doCallback(_key,'f',_error);\n        };\n        // check default headers\n        var _doCheckWithDefault = function(_headers,_key,_default){\n            var _value = _headers[_key]||\n                         _headers[_key.toLowerCase()];\n            if (!_value){\n                _value = _default;\n                _headers[_key] = _value;\n            }\n            return _value;\n        };\n        // pre convert array\n        var _doCheckData = function(_data,_key,_map){\n            if (_u._$isArray(_data)){\n                _map[_key] = JSON.stringify(_data);\n            }\n        };\n        // format rest url\n        var _doFormatURL = function(url, param, data, exist){\n            var getVal = function(key){\n                var _value = param[key];\n                if (_value!=null){\n                    exist[key] = !0;\n                }else{\n                    _value = data[key];\n                }\n                return encodeURIComponent(_value||'');\n            };\n            var ret = url.replace(_reg0,function($1,$2){\n                    return getVal($2)||$1;\n                }),\n                ret = ret.replace(_reg2,function($1,$2){\n                    var val = getVal($2);\n                    return !val?$1:('/'+val);\n                });\n            return ret;\n        };\n        return function(_url,_options){\n            _options = _u._$merge({},_options);\n            var _exist = {},\n                _param = _options.param||_o,\n                _data  = _options.data||{};\n            // parse uri template\n            _url = _doFormatURL(\n                _url,_param,\n                _data,_exist\n            );\n            // parse remain param\n            _u._$loop(\n                _param,function(_value,_key){\n                    if (!_exist[_key]){\n                        _data[_key] = _value;\n                    }\n                }\n            );\n            // parse headers\n            var _type = 'text',\n                _headers = _options.headers||{},\n                _accept  = _doCheckWithDefault(_headers,'Accept','application/json'),\n                _content = _doCheckWithDefault(_headers,'Content-Type','application/json');\n            // response data format\n            if (_jsn.test(_accept)){\n                _type = 'json';\n            }else if(_xml.test(_accept)){\n                _type = 'xml';\n            }\n            // do request\n            var _key = _u._$uniqueID();\n            _cache[_key] = {\n                s:_options.onload||_f,\n                f:_options.onerror||_f\n            };\n            // add params to url with GET/HEAD/DELETE method\n            // fix rest can't send null bug\n            _options.method = _options.method||'GET';\n            if (_reg1.test(_options.method.trim())||\n                _options.data==null){\n                _u._$forIn(_data,_doCheckData);\n                _options.query = _data;\n                _data = null;\n            }else if (_jsn.test(_content)){\n                _data = JSON.stringify(_data);\n            }\n            _options.type    = _type;\n            _options.data    = _data;\n            _options.headers = _headers;\n            _options.onload  = _onLoad._$bind(null,_key);\n            _options.onerror = _onError._$bind(null,_key);\n            return _j._$request(_url,_options);\n        };\n    })();\n    /**\n     * 中断请求\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/rest'\n     * ],function(_j){\n     *     var _id = _j._$request(\n     *         'http://123.163.com/rest/add',{\n     *             method:'POST',\n     *             data:{name:'ABC'},\n     *             timeout:60000,\n     *             onload:function(_data){\n     *                 // TODO\n     *             },\n     *             onerror:function(_error){\n     *                 // TODO\n     *             }\n     *         }\n     *     );\n     *     // 1秒后中断掉这个请求\n     *     window.setTimeout(\n     *         function(){\n     *             _j._$abort(_id);\n     *         },1000\n     *     );\n     * });\n     * ```\n     *\n     * @method module:util/ajax/rest._$abort\n     * @param  {String} arg0 - 请求标识\n     * @return {Void}\n     */\n    _p._$abort = function(_sn){\n        _j._$abort(_sn);\n    };\n    /**\n     * 通用载入出错回调函数，所有REST请求的异常均会进入此事件的回调逻辑中\n     *\n     * @event    external:window.onresterror\n     * @param    {Object}   event   - 错误信息\n     * @property {Number}   code    - 错误代码\n     * @property {String}   message - 错误描述\n     * @property {Variable} data    - 出错时携带数据\n     * @property {Boolean}  stopped - 是否阻止单个请求中的onerror回调\n     */\n    _t._$$CustomEvent._$allocate({\n        element:window,\n        event:'resterror'\n    });\n\n    if (CMPT){\n        NEJ.P('nej.j')._$requestByREST = _p._$request;\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/tag.js",
    "content": "/*\n * ------------------------------------------\n * 脚本载入控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/ajax/tag */\nNEJ.define([\n    'base/global',\n    'base/element',\n    'base/util',\n    './loader/text.js',\n    './loader/html.js',\n    './loader/style.js',\n    './loader/script.js'\n],function(NEJ,e,u,_t0,_t1,_t2,_t3,_p,_o,_f,_r){\n    /**\n     * 载入完成回调函数\n     *\n     * @callback module:util/ajax/tag.onload\n     * @param    {Variable} event - 请求返回数据\n     */\n    /**\n     * 载入出错回调函数\n     *\n     * @callback module:util/ajax/tag.onerror\n     * @param    {Object} event   - 错误信息\n     * @property {Number} code    - 错误码\n     * @property {String} message - 错误信息\n     */\n    /**\n     * 载入脚本文件\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/tag'\n     * ],function(_j){\n     *     _j._$loadScript('../../../javascript/log.js',{\n     *         onload:function(){\n     *             // 载入成功的回调方法\n     *         },\n     *         onerror:function(_error){\n     *             // 抛出异常回调\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/ajax/tag._$loadScript\n     * @see      module:util/ajax/tag._$queueScript\n     * @param    {String}  arg0    - 请求地址\n     * @param    {Object}  arg1    - 可选配置参数\n     * @property {Boolean} async   - 异步载入并立刻执行，默认为!0\n     * @property {Number}  timeout - 超时时间,0表示禁止超时监测\n     * @property {String}  version - 版本信息\n     * @property {String}  charset - 脚本编码\n     * @property {module:util/ajax/tag.onload}  onload  - 载入回调\n     * @property {module:util/ajax/tag.onerror} onerror - 异常回调\n     * @return   {Void}\n     */\n    _p._$loadScript = function(_url,_options){\n        _t3._$$LoaderScript._$allocate(_options)._$load(_url);\n    };\n    /**\n     * 载入队列脚本并依次执行\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/tag'\n     * ],function(_j){\n     *     _j._$queueScript([\n     *         '../../../javascript/log.js',\n     *         'http://123.163.com/a.js'\n     *     ],{\n     *         onload:function(){\n     *            // 载入成功的回调方法\n     *         },\n     *         onerror:function(_error){\n     *            // 异常回调方法\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/ajax/tag._$queueScript\n     * @see      module:util/ajax/tag._$loadScript\n     * @param    {Array}  arg0    - 脚本队列\n     * @param    {Object} arg1    - 可选配置参数\n     * @property {String} version - 版本信息\n     * @property {String} charset - 脚本编码\n     * @property {Number} timeout - 每个脚本超时时间,0表示禁止超时监测\n     * @property {module:util/ajax/tag.onload}  onload  - 载入回调\n     * @property {module:util/ajax/tag.onerror} onerror - 异常回调\n     * @return   {Void}\n     */\n    _p._$queueScript = function(_list,_options){\n        _t3._$$LoaderScript._$allocate(_options)._$queue(_list);\n    };\n    /**\n     * 载入样式文件\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/tag'\n     * ],function(_j){\n     *     _j._$loadStyle('http://123.163.com/a.css',{\n     *         onload:function(){\n     *             // 载入成功的回调方法\n     *         },\n     *         onerror:function(_error){\n     *             // 异常回调方法\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/ajax/tag._$loadStyle\n     * @see      module:util/ajax/tag._$queueStyle\n     * @param    {String} arg0    - 样式文件地址\n     * @param    {Object} arg1    - 可选配置参数\n     * @property {Number} timeout - 超时时间,0表示禁止超时监测\n     * @property {String} version - 版本信息\n     * @property {module:util/ajax/tag.onload}  onload  - 载入回调\n     * @property {module:util/ajax/tag.onerror} onerror - 异常回调\n     * @return   {Void}\n     */\n    _p._$loadStyle = function(_url,_options){\n        _t2._$$LoaderStyle._$allocate(_options)._$load(_url);\n    };\n    /**\n     * 载入样式队列\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/tag'\n     * ],function(_j){\n     *     _j._$queueStyle([\n     *         'http://123.163.com/a.css',\n     *         'http://123.163.com/b.css'\n     *     ],{\n     *         onload:function(){\n     *             // 载入成功的回调方法\n     *         },\n     *         onerror:function(_error){\n     *             // 异常回调方法\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/ajax/tag._$queueStyle\n     * @see      module:util/ajax/tag._$loadStyle\n     * @param    {Array}  arg0    - 样式队列\n     * @param    {Object} arg1    - 可选配置参数\n     * @property {Number} timeout - 超时时间,0表示禁止超时监测\n     * @property {String} version - 版本信息\n     * @property {module:util/ajax/tag.onload}  onload  - 载入回调\n     * @property {module:util/ajax/tag.onerror} onerror - 异常回调\n     * @return   {Void}\n     */\n    _p._$queueStyle = function(_list,_options){\n        _t2._$$LoaderStyle._$allocate(_options)._$queue(_list);\n    };\n    /**\n     * 载入HTML文件\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/tag'\n     * ],function(_j){\n     *     _j._$loadHtml('http://123.163.com/a.html',{\n     *         onload:function(){\n     *             // 载入成功的回调方法\n     *         },\n     *         onerror:function(_error){\n     *             // 异常回调方法\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/ajax/tag._$loadHtml\n     * @param    {String} arg0    - 文件地址\n     * @param    {Object} arg1    - 可选配置参数\n     * @property {String} version - 版本信息\n     * @property {module:util/ajax/tag.onload}  onload  - 载入回调\n     * @property {module:util/ajax/tag.onerror} onerror - 异常回调\n     * @return   {Void}\n     */\n    _p._$loadHtml = function(_url,_options){\n        _t1._$$LoaderHtml._$allocate(_options)._$load(_url);\n    };\n    /**\n     * 载入NEJ模板文件\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/tag'\n     * ],function(_j){\n     *     _j._$loadTemplate('http://123.163.com/a.html',{\n     *         onload:function(){\n     *             // 载入成功的回调方法\n     *         },\n     *         onerror:function(_error){\n     *             // 异常回调方法\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/ajax/tag._$loadTemplate\n     * @param    {String} arg0    - 文件地址\n     * @param    {Object} arg1    - 可选配置参数\n     * @property {String} version - 版本信息\n     * @property {module:util/ajax/tag.onload}  onload  - 载入回调\n     * @property {module:util/ajax/tag.onerror} onerror - 异常回调\n     * @return   {Void}\n     */\n    _p._$loadTemplate = function(_url,_options){\n        var org1 = u._$url2origin(_url),\n            org2 = u._$url2origin(location.href);\n        if (!org1||org1==org2){\n            _p._$loadHtml(_url, _options);\n        }else{\n            var callback = _options.onload;\n            _options.onload = function(event){\n                if (!!event){\n                    callback(e._$html2node(event.content));\n                }\n            };\n            _p._$loadText(_url, _options);\n        }\n    };\n    /**\n     * 载入HTML文件\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/tag'\n     * ],function(_j){\n     *     _j._$loadText('http://123.163.com/a.txt',{\n     *         onload:function(){\n     *             // 载入成功的回调方法\n     *         },\n     *         onerror:function(_error){\n     *             // 异常回调方法\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/ajax/tag._$loadText\n     * @param    {String} arg0    - 文件地址\n     * @param    {Object} arg1    - 可选配置参数\n     * @property {String} version - 版本信息\n     * @property {module:util/ajax/tag.onload}  onload  - 载入回调\n     * @property {module:util/ajax/tag.onerror} onerror - 异常回调\n     * @return {Void}\n     */\n    _p._$loadText = function(_url,_options){\n        _t0._$$LoaderText._$allocate(_options)._$load(_url);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.j'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/ajax/test/a.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>message test</title>\n    </head>\n    <body>\n        <button id=\"openIframe\">打开IFrame</button>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./a.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/ajax/test/a.js",
    "content": "NEJ.define(['{lib}base/event.js','{lib}util/ajax/message.js'],function(_v,_j){\n    _v._$addEvent('openIframe','click',function(){\n        var _iframe = document.createElement('iframe');\n        _iframe.src = 'http://b.c.com:8000/util/ajax/test/b.html';\n        _iframe.id = \"loginFrame\";\n        document.body.appendChild(_iframe);\n        _iframe.style.width = '200px';\n        _iframe.style.height = '400px';\n        _iframe.style.position = 'absolute';\n        _iframe.style.border = '1px solid #ccc';\n        _iframe.style.zIndex = '9999';\n        _iframe.style.top = '100px';\n        _iframe.style.left = '50%';\n        _iframe.style.marginLeft = '-100px';\n    });\n\n    _v._$addEvent(window,'message',function(_event){\n        alert(_event.data);\n    })\n});\n"
  },
  {
    "path": "src/util/ajax/test/b.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>message test</title>\n    </head>\n    <body>\n        <button id=\"sendMsg\">sendMsg</button>\n        <button onclick=\"top.name='xxxx'\">set</button>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./b.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/ajax/test/b.js",
    "content": "NEJ.define(['lib/base/event','{lib}util/ajax/message.js'],function(_v,_j){\n    _v._$addEvent('sendMsg','click',function(_event){\n        _j._$postMessage('_top',{data:'{\"name\":\"nihao\"}'});\n    });\n});\n"
  },
  {
    "path": "src/util/ajax/test/message.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>message测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n    </head>\n    <body>\n    \t<script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./message.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/ajax/test/message.test.js",
    "content": "var f = function(){\n\tvar _  = NEJ.P,\n\t    _v = _('nej.v'),\n\t\t_j = _('nej.j');\n\t_v._$addEvent(window,'message',function(_event){\n\t\tnej.j._$postMessage(_event.source,{\n                    data:'你好！',\n                    origin:_event.origin\n                });\n\t});\n}\nNEJ.define('{pro}message.test.js',\n    ['{lib}util/ajax/message.js'],f);\n"
  },
  {
    "path": "src/util/ajax/test/tag.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>tag测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit xdr test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./tag.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/ajax/test/tag.test.js",
    "content": "NEJ.define([\n    'util/ajax/tag'\n],function(_t){\n    module('tag');\n    var _j = NEJ.P('nej.j');\n    test('loadScript',function(){\n        expect(1);\n        stop();\n        _j._$loadScript('../rest.js',{\n             onload:function(){\n                ok(true, '载入成功的回调方法');\n                start();\n                 // 载入成功的回调方法\n             },\n             onerror:function(_error){\n                start();\n                 // 抛出异常回调\n             }\n         });\n    });\n\n    test('queueScript',function(){\n        expect(1);\n        stop();\n        _j._$queueScript(['../xdr.js','../dwr.js'],{\n             onload:function(){\n                ok(true, '载入成功的回调方法');\n                    start();\n                 // 载入成功的回调方法\n             },\n             onerror:function(_error){\n                start();\n                 // 抛出异常回调\n             }\n         });\n    });\n\n    test('loadStyle',function(){\n        expect(1);\n        stop();\n        _j._$loadStyle('./x.css',{\n             onload:function(){\n                ok(true, '载入成功的回调方法');\n                    start();\n                 // 载入成功的回调方法\n             },\n             onerror:function(_error){\n                start();\n                 // 抛出异常回调\n             }\n         });\n    });\n\n    test('queueStyle',function(){\n        expect(1);\n        stop();\n        _j._$queueStyle(['./x.css','./xx.css'],{\n             onload:function(){\n                ok(true, '载入成功的回调方法');\n                    start();\n                 // 载入成功的回调方法\n             },\n             onerror:function(_error){\n                start();\n                 // 抛出异常回调\n             }\n         });\n    });\n\n    test('loadHtml',function(){\n        expect(1);\n        stop();\n        _j._$loadHtml('./message.test.html',{\n             onload:function(){\n                ok(true, '载入成功的回调方法');\n                    start();\n                 // 载入成功的回调方法\n             },\n             onerror:function(_error){\n                start();\n                 // 抛出异常回调\n             }\n         });\n    });\n\n    test('loadText',function(){\n        expect(1);\n        stop();\n        _j._$loadText('./xxx.txt',{\n             onload:function(){\n                ok(true, '载入成功的回调方法');\n                    start();\n                 // 载入成功的回调方法\n             },\n             onerror:function(_error){\n                start();\n                 // 抛出异常回调\n             }\n         });\n    });\n});"
  },
  {
    "path": "src/util/ajax/test/x.css",
    "content": "x.css"
  },
  {
    "path": "src/util/ajax/test/xdr.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>xdr测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n  \t\t<script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit xdr test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<form id=\"upload\" name=\"upload\" action=\"http://123.163.com:3000/xhr/uploadCallback\">\n\t\t\t<input type=\"file\" name=\"fileUpload\" id=\"fileUpload\" multiple=\"multiple\" />\n\t\t\t<input type=\"text\" id=\"progress\" />\n\t\t\t<input type=\"hidden\" name=\"nej_cookie\" value=\"false\"/>\n\t\t\t<input type=\"hidden\" name=\"nej_mode\" value=\"2\" />\n\t\t\t<input type=\"hidden\" name=\"nej_query\" value=\"http://123.163.com:3000/xhr/progress\" />\n\t\t</form>\n\t\t<script id=\"hiddenlpsubmitdiv\" style=\"display: none;\"></script>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./xdr.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/util/ajax/test/xdr.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"xdr\",{\n        setup:function(){\n            this._p = NEJ.P('nej.p');\n            this._e = NEJ.P('nej.e');\n            this._j = NEJ.P('nej.j');\n        },\n        teardown:function(){\n\n        }\n    });\n\n    //开始单元测试\n    test('正常的xdr', function() {\n        expect(0);\n        stop();\n        var _url = 'http://123.163.com:3000/xhr/getLog';\n\t\tvar _obj = {};\n        this._j._$request(_url,{\n                type:'json',\n                method:'post',\n                data:_obj,\n                timeout:1000,\n                onload:function(_data){\n                    start();\n                    if(!!_data)\n                        ok(true,'请求正常返回，返回值是' + _data.name);\n                },\n                onerror:function(_error){\n                    start();\n                }}\n            );\n    });\n\n//\ttest('设置过滤器的xdr', function() {\n//        stop();\n//\t\tthis._j._$filter(function(_event){\n//\t\t\tif(_event.type == 'onerror'){\n//\t\t\t\t// 如果过滤掉，测试无法完成\n//\t\t\t\tif(_event.result.data == 404)\n//\t\t\t\t    _event.stopped = false;\n//\t\t\t}\n//\t\t});\n//        this._j._$request('http://123.163.com:3003/xhr/xxx',{\n//                type:'json',\n//                method:'POST',\n//                data:{name:'cheng-lin'},\n//                timeout:3000,\n//                onload:function(_data){\n//                    if(!!_data)\n//                        ok(true,'请求正常返回，返回值是' + _data.name);\n//                    start();\n//                },\n//                onerror:function(_error){\n//                    start();\n//                }}\n//            );\n//    });\n//\n//\ttest('中途中断请求',function(){\n//\t\tstop();\n//        var _reqID = this._j._$request('http://123.163.com:3003/xhr/xxx',{\n//               type:'json',\n//               method:'POST',\n//               data:{name:'cheng-lin'},\n//               timeout:60000,\n//               onload:function(_data){\n//\t\t\t\tstart();\n//               },\n//               onerror:function(_error){\n//\t\t\t\tstart();\n//               }}\n//           );\n//       // 1秒后中断掉这个请求\n//       window.setTimeout(function(){\n//           this._j._$abort(_reqID);\n//       }._$bind(this),1000);\n//\t});\n//\n//\ttest('upload表单,高级浏览器',function(){\n//\t\tvar _upload = this._e._$get('upload');\n//\t\tthis._j._$upload(_upload,{mode:0,nocookie:false,\n//\t\t\tonuploading:function(_data){\n//\t\t\t\tif(!!_data.total&&_data.progress){\n//\t                ok(true,'打印出一个进度来'+_data.progress)\n//\t\t\t\t}\n//\t\t\t},onload:function(_url){\n//\t            start();\n//\t        }\n//\t\t});\n//\t});\n//\n\ttest('upload表单,低版本浏览器',function(){\n\t\tstop();\n        var _upload = this._e._$get('upload');\n\t\tvar _progress = this._e._$get('progress');\n        this._j._$upload(_upload,{mode:0,nocookie:true,\n\t\tonuploading:function(_data){\n            if(!!_data.total&&_data.progress){\n\t\t\t\t_progress.value = _data.progress;\n                ok(true,'打印出一个进度来'+_data.progress)\n            }\n        },\n\t\tonload:function(_url){\n\t\t\tok(true,_url.url);\n\t\t\tstart();\n\t\t}});\n    });\n\n}\nNEJ.define(['{lib}util/ajax/xdr.js'],f);\n"
  },
  {
    "path": "src/util/ajax/test/xx.css",
    "content": "xx.css"
  },
  {
    "path": "src/util/ajax/test/xxx.txt",
    "content": "xxx.txt"
  },
  {
    "path": "src/util/ajax/xdr.js",
    "content": "﻿/*\n * ------------------------------------------\n * XDR控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/ajax/xdr */\nNEJ.define([\n    'base/global',\n    'base/constant',\n    'base/util',\n    'base/element',\n    './proxy/xhr.js',\n    '{platform}xdr.js'\n],function(NEJ,_g,_u,_e,_t,_h,_p,_o,_f,_r){\n    /**\n     * 载入回调\n     *\n     * @callback module:util/ajax/xdr.onload\n     * @param    {Variable|Object} event - 请求返回数据，根据请求时type指定格式返回，\n     *                                     如果请求时指定了result参数，则此处输入为包含额外信息的对象，\n     *                                     数据结果从此对象的data属性中取，如{headers:{'x-res-0':'12345', ...},data:{a:'aaa', ...}}\n     */\n    /**\n     * 出错回调\n     *\n     * @callback module:util/ajax/xdr.onerror\n     * @param    {Object}   event   - 错误信息\n     * @property {Number}   code    - 错误代码\n     * @property {String}   message - 错误描述\n     * @property {Variable} data    - 出错时携带数据\n     */\n    /**\n     * 请求之前对数据处理回调\n     *\n     * @callback module:util/ajax/xdr.onbeforerequest\n     * @param    {Object} event   - 请求信息\n     * @property {Object} request - 请求参数，数据信息 url/sync/cookie/type/method/timeout\n     * @property {Object} headers - 请求头信息\n     */\n    /**\n     * 上传进度回调\n     *\n     * @callback module:util/ajax/xdr.onuploading\n     * @param    {Object} event  - 进度信息\n     * @property {Number} loaded - 载入数量\n     * @property {Number} total  - 总量\n     */\n    // sn:{req:proxy,onload:function(){},onerror:function(){}}\n    var _xcache = {},\n        _doFilter = _f;\n    /**\n     * 中断请求\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/xdr'\n     * ],function(_j){\n     *     var _id = _j._$request(\n     *         'http://123.163.com/xhr/',{\n     *             type:'json',\n     *             method:'POST',\n     *             data:{name:'ABC'},\n     *             timeout:60000,\n     *             onload:function(_data){\n     *                 // TODO\n     *             },\n     *             onerror:function(_error){\n     *                 // TODO\n     *             }\n     *         }\n     *     );\n     *     // 1秒后中断掉这个请求\n     *     window.setTimeout(\n     *         function(){\n     *             _j._$abort(_id);\n     *         },1000\n     *     );\n     * });\n     * ```\n     *\n     * @method module:util/ajax/xdr._$abort\n     * @param  {String} arg0 - 请求标识\n     * @return {Void}\n     */\n    _p._$abort = function(_sn){\n        var _cache = _xcache[_sn];\n        if (!!_cache){\n            _cache.req._$abort();\n        }\n    };\n    /**\n     * 全局请求过滤器，过滤器中可以通过设置输入事件对象的stopped值阻止继续回调\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/xdr'\n     * ],function(_j){\n     *     _j._$filter(function(_event){\n     *         // _event.type     请求过滤类型\n     *         // _event.result   请求结果\n     *         // _event.stopped  是否阻止后续逻辑\n     *\n     *         // 过滤掉404的异常，如果type是onload不做处理\n     *         if (_event.type == 'onerror'){\n     *             if (_event.result.data == 404){\n     *                 _event.stopped = false;\n     *             }\n     *         }\n     *     });\n     *     _j._$request('xxxx',{\n     *         type:'json',\n     *         method:'POST',\n     *         data:{name:'abc'},\n     *         timeout:3000,\n     *         onload:function(_data){\n     *             // TODO\n     *         },\n     *         onerror:function(_error){\n     *             // TODO\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method module:util/ajax/xdr._$filter\n     * @param  {Function} arg0 - 过滤器\n     * @return {Void}\n     */\n    _p._$filter = function(_filter){\n        _doFilter = _filter||_f;\n    };\n    /**\n     * 发送ajax请求\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/xdr'\n     * ],function(_p){\n     *     var _id = _p._$request(\n     *         'http://a.b.com/api',{\n     *             sync:true,\n     *             type:'json',\n     *             data:'hello',\n     *             query:'a=1&b=2',\n     *             method:'post',\n     *             timeout:3000,\n     *             mode:0||1||2||3,\n     *             onload:function(_data){\n     *                 // 正常回调处理\n     *             },\n     *             onerror:function(_error){\n     *                 // 异常处理\n     *             },\n     *             onbeforerequest:function(_data){\n     *                 // 请求发送前，对请求数据处理\n     *             }\n     *         }\n     *     );\n     * });\n     * ```\n     *\n     * @method   module:util/ajax/xdr._$request\n     * @param    {String}   arg0    - 请求地址\n     * @param    {Object}   arg1    - 配置参数\n     * @property {Boolean}  sync    - 是否同步请求\n     * @property {String}   type    - 返回数据格式,text/json/xml\n     * @property {Variable} data    - 要发送的数据\n     * @property {Variable} query   - 查询参数,字符串格式a=b&c=d,对象格式{a:'b',c:'d'}\n     * @property {String}   method  - 请求方式,GET/POST\n     * @property {Number}   timeout - 超时时间,0 禁止超时监测\n     * @property {Object}   headers - 头信息表，标准HTTP头字段\n     * @property {Boolean}  cookie  - 跨域请求是否带cookie，仅对CORS方式有效\n     * @property {Number}   mode    - 请求模式,针对跨域请求采用的请求方式\n     *\n     * * 0 - 自动模式，高版本使用HTML5的CORS协议，低版本采用Frame代理方式\n     * * 1 - 高版本使用HTML5的CORS协议，低版本采用Flash代理方式\n     * * 2 - 全部使用Frame代理方式\n     * * 3 - 全部使用Flash代理方式\n     *\n     * @property {Object}   result  - onload回调输入时需包含的额外信息，已处理额外数据\n     *\n     * * headers - 服务器返回头信息，如{headers:'x-res-0'}或者{headers:['x-res-0','x-res-1']}\n     *\n     * @property {module:util/ajax/xdr.onload}          onload  - 数据载入回调\n     * @property {module:util/ajax/xdr.onerror}         onerror - 请求异常回调\n     * @property {module:util/ajax/xdr.onbeforerequest} onbeforerequest - 请求之前回调\n     *\n     * @return   {String} 分配给请求的ID\n     */\n    _p._$request = (function(){\n        var _location = (location.protocol+'//'\n                        +location.host).toLowerCase();\n        // check cross-domain request\n        var _isXDomain = function(_url){\n            var _origin = _u._$url2origin(_url);\n            return !!_origin&&_origin!=_location;\n        };\n        // check file upload\n        var _isUpload = function(_headers){\n            return (_headers||_o)[_g._$HEAD_CT]==_g._$HEAD_CT_FILE;\n        };\n        // get ajax proxy\n        var _getProxy = function(_options){\n            var _upload = _isUpload(_options.headers);\n            if (!_isXDomain(_options.url)&&!_upload)\n                return _t._$$ProxyXHR._$allocate(_options);\n            return _h.__getProxyByMode(_options.mode,_upload,_options);\n        };\n        // parse ext result\n        var _doParseExtData = function(_cache,_result){\n            var _data = {\n                data:_result\n            };\n            // parse ext headers\n            var _keys = _cache.result.headers;\n            if (!!_keys){\n                _data.headers = _cache.req._$header(_keys);\n            }\n            // TODO parse other ext data\n            return _data;\n        };\n        // clear cache\n        var _doClear = function(_sn){\n            var _cache = _xcache[_sn];\n            if (!_cache) return;\n            if (!!_cache.req)\n                _cache.req._$recycle();\n            delete _xcache[_sn];\n        };\n        // do callback\n        var _doCallback = function(_sn,_type){\n            var _cache = _xcache[_sn];\n            if (!_cache) return;\n            var _data = arguments[2];\n            if (_type=='onload'&&!!_cache.result){\n                _data = _doParseExtData(_cache,_data);\n            }\n            _doClear(_sn);\n            var _event = {\n                type:_type,\n                result:_data\n            };\n            _doFilter(_event);\n            if (!_event.stopped){\n               (_cache[_type]||_f)(_event.result);\n            }\n        };\n        // onload callback\n        var _onLoad = function(_sn,_data){\n            _doCallback(_sn,'onload',_data);\n        };\n        // onerror callback\n        var _onError = function(_sn,_error){\n            _doCallback(_sn,'onerror',_error);\n        };\n        // check data for get method\n        var _doMergeURL = function(_url,_data){\n            var _sep = _url.indexOf('?')<0?'?':'&',\n                _data = _data||'';\n            if (_u._$isObject(_data))\n                _data = _u._$object2query(_data);\n            if (!!_data) _url += _sep+_data;\n            return _url;\n        };\n        // function body\n        return function(_url,_options){\n            _options = _options||{};\n            // cache request callback\n            var _sn = _u._$uniqueID(),\n                _cache = {\n                    result:_options.result,\n                    onload:_options.onload||_f,\n                    onerror:_options.onerror||_f\n                };\n            _xcache[_sn] = _cache;\n            _options.onload = _onLoad._$bind(null,_sn);\n            _options.onerror = _onError._$bind(null,_sn);\n            // append request query\n            if (!!_options.query){\n                _url = _doMergeURL(_url,_options.query);\n            }\n            // append request data for get\n            var _method = _options.method||'';\n            if ((!_method||/get/i.test(_method))&&!!_options.data){\n                _url = _doMergeURL(_url,_options.data);\n                _options.data = null;\n            }\n            _options.url = _url;\n            _cache.req = _getProxy(_options);\n            _cache.req._$send(_options.data);\n            return _sn;\n        };\n    })();\n    /**\n     * 文件上传\n     *\n     * 结构举例\n     * ```html\n     * <form id=\"upload\" name=\"upload\" action=\"http://123.163.com:3000/xhr/uploadCallback\">\n     *    <input type=\"text\" id=\"progress\" />\n     *    <input type=\"hidden\" name=\"nej_mode\" value=\"2\" />\n     *    <input type=\"hidden\" name=\"nej_query\" value=\"http://123.163.com:3000/xhr/progress\" />\n     * </form>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/xdr'\n     * ],function(_j){\n     *     _j._$upload('upload',{\n     *         mode:2,\n     *         cookie:true,\n     *         onuploading:function(_data){\n     *             // 后台处理http://123.163.com:3000/xhr/progress，返回一个json对象\n     *             // 前台会去轮询此接口获取进度\n     *             if(!!_data.total&&_data.progress){\n     *                 _progress.value = _data.progress;\n     *             }\n     *         },\n     *         onload:function(_url){\n     *             // 此前会把进度轮询终止掉。如果要显示进度100%，可在此设置一次\n     *             // 后台处理http://123.163.com:3000/xhr/uploadCallback，返回url\n     *             // 文件上传完成的回调,url为返回的地址\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/ajax/xdr._$upload\n     * @see      module:util/ajax/xdr._$request\n     * @param    {HTMLFormElement}  arg0    - 表单对象，待上传的文件及目标地址信息封装在此对象中\n     * @param    {Object}           arg1    - 可选配置参数\n     * @property {String}           type    - 返回数据格式\n     * @property {Variable}         query   - 查询参数\n     * @property {Number}           mode    - 跨域类型，0/2，见_$request接口说明\n     * @property {Object}           headers - 头信息\n     * @property {Boolean}          cookie  - 跨域请求是否带cookie，仅对CORS方式有效\n     *\n     * @property {module:util/ajax/xdr.onload}          onload  - 数据载入回调\n     * @property {module:util/ajax/xdr.onerror}         onerror - 请求异常回调\n     * @property {module:util/ajax/xdr.onuploading}     onuploading     - 上传进度回调\n     * @property {module:util/ajax/xdr.onbeforerequest} onbeforerequest - 请求之前回调\n     *\n     * @return   {String}                     分配给请求的ID\n     */\n    _p._$upload = function(_form,_options){\n        _form = _e._$get(_form);\n        if (!_form){\n            return '';\n        }\n        // init param\n        var _option = _u._$fetch({\n            mode:0,\n            type:'json',\n            query:null,\n            cookie:!1,\n            headers:{},\n            onload:null,\n            onerror:null,\n            onuploading:null,\n            onbeforerequest:null\n        },_options);\n        _option.data = _form;\n        _option.method = 'POST';\n        _option.timeout = 0;\n        _option.headers[_g._$HEAD_CT] =\n                        _g._$HEAD_CT_FILE;\n        return _p._$request(_form.action,_option);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.j'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/animation/animation.js",
    "content": "/*\n * ------------------------------------------\n * 动画基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/animation/animation */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/event',\n    'util/timer/animation'\n],function(NEJ,_k,_t,_t0,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 动画基类\n     * \n     * @class   module:util/animation/animation._$$Animation\n     * @extends module:util/event._$$EventTarget\n     *\n     * @param    {Object} config - 可选配置参数\n     * @property {Object} to     - 动画结束信息\n     * @property {Object} from   - 动画初始信息\n     * @property {Number} delay  - 延时时间，单位毫秒，默认0\n     */\n    /**\n     * 动画结束回调事件\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/animation/bounce'\n     * ],function(_t){\n     *     var _bounce = _t._$$AnimBounce._$allocate({\n     *         from: {\n     *             offset: 100,\n     *             velocity: 100\n     *         },\n     *         acceleration:100,\n     *         onstop: function(){\n     *             // 动画停止后回收控件\n     *             _bounce = nej.ut._$$AnimBounce._$recycle(_bounce);\n     *         }\n     *     });\n     * });\n     * ```\n     * \n     * @event module:util/animation/animation._$$Animation#onstop\n     */\n    /**\n     * 动画过程回调事件\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/animation/bounce'\n     * ],function(_t){\n     *     var _bounce = _t._$$AnimBounce._$allocate({\n     *         from: {\n     *             offset: 100,\n     *             velocity: 100\n     *         },\n     *         acceleration:100,\n     *         onupdate: function(_event){\n     *             // 坐标\n     *             console.log(_event.offset + 'px');\n     *             // 初速度\n     *             console.log(_event.velocity);\n     *         }\n     *     });\n     * });\n     * ```\n     * \n     * @event    module:util/animation/animation._$$Animation#onupdate\n     * @param    {Object} event    - 可选配置参数\n     * @property {Number} offset   - 偏移量\n     * @property {Number} velocity - 初速度(px/s)\n     */\n    _p._$$Animation = _k._$klass();\n    _pro = _p._$$Animation._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method   module:util/animation/animation._$$Animation#__reset\n     * @param    {Object} arg0 - 可选配置参数\n     * @property {Number} to   - 结束坐标\n     * @property {Number} from - 起始坐标\n     * @return   {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__end = _options.to||_o;\n        this.__begin = _options.from||{};\n        this.__delay = Math.max(\n            0,parseInt(_options.delay)||0\n        );\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/animation/animation._$$Animation#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        this._$stop();\n        if (!!this.__dtime){\n            window.clearTimeout(this.__dtime);\n            delete this.__dtime;\n        }\n        delete this.__end;\n        delete this.__begin;\n    };\n    /**\n     * 动画帧逻辑\n     * \n     * @protected\n     * @method module:util/animation/animation._$$Animation#__onAnimationFrame\n     * @param  {Number} arg0 - 时间值\n     * @return {Void}\n     */\n    _pro.__onAnimationFrame = function(_time){\n        if (!this.__begin) return;\n        // fix safari12 without \".\" for performance.now()\n        var ts = ''+Math.floor(_time);\n        if (ts.length<13){\n            _time = +new Date;\n        }\n        // if ((''+_time).indexOf('.')>=0){\n        //     _time = +new Date;\n        // }\n        if (this.__doAnimationFrame(_time)){\n            this._$stop();\n            return;\n        }\n        this.__timer = _t0.requestAnimationFrame(\n            this.__onAnimationFrame._$bind(this)\n        );\n    };\n    /**\n     * 动画帧回调，子类实现具体算法\n     * \n     * @abstract\n     * @method module:util/animation/animation._$$Animation#__doAnimationFrame\n     * @param  {Number}  arg0 - 时间值\n     * @return {Boolean}        是否停止动画\n     */\n    _pro.__doAnimationFrame = _f;\n    /**\n     * 注册动画监听事件\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/animation/bounce'\n     * ],function(_t){\n     *     var _bounce = _t._$$AnimBounce._$allocate({\n     *         from: {\n     *             offset: 100,\n     *             velocity: 100\n     *         },\n     *         acceleration:100,\n     *         onupdate: function(_event){\n     *             // 坐标\n     *             console.log(_event.offset + 'px');\n     *             // 初速度\n     *             console.log(_event.velocity);\n     *         }\n     *     });\n     *     // 进行弹性动画\n     *     _bounce._$play();\n     * });\n     * ```\n     * \n     * @method module:util/animation/animation._$$Animation#_$play\n     * @return {Void}\n     */\n    _pro._$play = (function(){\n        var _doPlayAnim = function(){\n            this.__dtime = window.clearTimeout(this.__dtime);\n            this.__begin.time = +new Date;\n            this.__timer = _t0.requestAnimationFrame(\n                this.__onAnimationFrame._$bind(this)\n            );\n        };\n        return function(){\n            this.__dtime = window.setTimeout(\n                _doPlayAnim._$bind(this),\n                this.__delay\n            );\n        };\n    })();\n    /**\n     * 取消动画监听事件\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/animation/bounce'\n     * ],function(_t){\n     *     var _bounce = _t._$$AnimBounce._$allocate({\n     *         from: {\n     *             offset: 100,\n     *             velocity: 100\n     *         },\n     *         acceleration:100,\n     *         onupdate: function(_event){\n     *             // 坐标\n     *             console.log(_event.offset + 'px');\n     *             // 初速度\n     *             console.log(_event.velocity);\n     *         }\n     *     });\n     *     // 进行动画\n     *     _bounce._$play();\n     *     // 停止动画,触发onstop\n     *     _bounce._$stop();\n     * });\n     * ```\n     *\n     * @method module:util/animation/animation._$$Animation#_$stop\n     * @return {Void}\n     */\n    _pro._$stop = function(){\n        this.__timer = _t0.cancelAnimationFrame(this.__timer);\n        this._$dispatchEvent('onstop');\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/animation/bezier.js",
    "content": "/*\n * ------------------------------------------\n * 贝塞尔曲线算法实现文件\n * 算法参考webkit动画实现\n * WebCore/platform/graphics/UnitBezier.h\n * WebCore/page/animation/AnimationBase.cpp\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/animation/bezier */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    './animation.js'\n],function(NEJ,_k,_u,_t0,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 贝塞尔曲线算法\n     * \n     * 初始信息包括\n     * \n     * * offset  [Number]  偏移量 \n     *\n     * 结束信息包括\n     * \n     * * offset  [Number]  偏移量 \n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/animation/bezier'\n     * ],function(_t){\n     *     var _easein = nej.ut._$$AnimBezier._$allocate({\n     *         from: {\n     *             offset: 100\n     *         },\n     *         to:{\n     *             offset: 0\n     *         },\n     *         timing:'easein',\n     *         onupdate:function(_event){\n     *             // 坐标\n     *             console.log(_event.offset + 'px');\n     *             // 更新节点位置\n     *         },\n     *         onstop:function(){\n     *             // 动画停止后回收控件\n     *             this._$recycle();\n     *         }\n     *     });\n     *     // 进行弹性动画\n     *     _easein._$play();\n     * });\n     * ```\n     * \n     * @class    module:util/animation/bezier._$$AnimBezier\n     * @extends  module:util/animation/animation._$$Animation\n     * \n     * @param    {Object} config   - 可选配置参数\n     * @property {Number} duration - 持续时间，单位毫秒，默认为200ms\n     * @property {String} timing   - 时间函数，默认为ease，ease/easein/easeout/easeinout/linear/cubic-bezier(x1,y1,x2,y2)\n     */\n    _p._$$AnimBezier = _k._$klass();\n    _pro = _p._$$AnimBezier._$extend(_t0._$$Animation);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/animation/bezier._$$AnimBezier#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__duration = _options.duration||200;\n        this.__epsilon  = 1/(200*this.__duration);\n        this.__doParseTiming(_options.timing);\n        this.__doCalPolynomialCoefficients();\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/animation/bezier._$$AnimBezier#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__pointer;\n        delete this.__coefficient;\n    };\n    /**\n     * 解析时间动画为坐标信息\n     * \n     * @protected\n     * @method module:util/animation/bezier._$$AnimBezier#__doParseTiming\n     * @param  {String} arg0 - 时间动画\n     * @return {Void}\n     */\n    _pro.__doParseTiming = (function(){\n        var _reg0 = /^cubic\\-bezier\\((.*?)\\)$/i,\n            _reg1 = /\\s*,\\s*/i,\n            _pointers = {\n                linear:[0,0,1,1]\n               ,ease:[0.25,0.1,0.25,1.0]\n               ,easein:[0.42,0,1,1]\n               ,easeout:[0,0,0.58,1]\n               ,easeinout:[0,0,0.58,1]\n            };\n        var _doParseFloat = function(_value,_index,_list){\n            _list[_index] = parseFloat(_value);\n        };\n        return function(_timing){\n            _timing = (_timing||'').toLowerCase();\n            this.__pointer = _pointers[_timing];\n            if (_reg0.test(_timing)){\n                this.__pointer = RegExp.$1.split(_reg1);\n                _u._$forEach(this.__pointer,_doParseFloat);\n            }\n            if (!!this.__pointer) return;\n            this.__pointer = _pointers.ease;\n        };\n    })();\n    /**\n     * 计算贝塞尔曲线多项式系数\n     * \n     * @protected\n     * @method module:util/animation/bezier._$$AnimBezier#__doCalPolynomialCoefficients\n     * @return {Void}\n     */\n    _pro.__doCalPolynomialCoefficients = function(){\n        var _pt = this.__pointer,\n            _cx = 3*_pt[0],\n            _bx = 3*(_pt[2]-_pt[0])-_cx,\n            _ax = 1-_cx-_bx,\n            _cy = 3*_pt[1],\n            _by = 3*(_pt[3]-_pt[1])-_cy,\n            _ay = 1-_cy-_by;\n        this.__coefficient = {\n            ax:_ax, ay:_ay,\n            bx:_bx, by:_by,\n            cx:_cx, cy:_cy\n        };\n    };\n    /**\n     * 计算目标接近率\n     * \n     * @protected\n     * @method module:util/animation/bezier._$$AnimBezier#__doCalCubicBezierAtTime\n     * @param  {Number} arg0 - 当前时间\n     * @return {Float}         终点接近率\n     */\n    _pro.__doCalCubicBezierAtTime = (function(){\n        var _doSampleCurveX = function(_time,_coef){\n            return ((_coef.ax*_time+_coef.bx)*_time+_coef.cx)*_time;\n        };\n        var _doSampleCurveY = function(_time,_coef){\n            return ((_coef.ay*_time+_coef.by)*_time+_coef.cy)*_time;\n        };\n        var _doSampleCurveDerivativeX = function(_time,_coef){\n            return (3*_coef.ax*_time+2*_coef.bx)*_time+_coef.cx;\n        };\n        var _doSolveCurveX = function(_time,_epsilon,_coef){\n            var t0,t1,t2,x2,d2,i;\n            // First try a few iterations of Newton's method -- normally very fast.\n            for(t2=_time,i=0;i<8;i++){\n                x2 = _doSampleCurveX(t2,_coef)-_time;\n                if (Math.abs(x2)<_epsilon)\n                    return t2;\n                d2 = _doSampleCurveDerivativeX(t2,_coef);\n                if (Math.abs(d2)<1e-6)\n                    break;\n                t2 = t2-x2/d2;\n            }\n            // Fall back to the bisection method for reliability.\n            t0 = 0; t1 = 1; t2 = _time;\n            if (t2<t0) return t0;\n            if (t2>t1) return t1;\n            while(t0<t1) {\n                x2 = _doSampleCurveX(t2,_coef);\n                if (Math.abs(x2-_time)<_epsilon)\n                    return t2;\n                if (_time>x2)\n                    t0 = t2;\n                else\n                    t1 = t2;\n                t2 = (t1-t0)*0.5+t0;\n            }\n            // Failure.\n            return t2;\n        };\n        return function(_delta){\n            return _doSampleCurveY(\n                   _doSolveCurveX(_delta/this.__duration,\n                   this.__epsilon,this.__coefficient),this.__coefficient);\n        };\n    })();\n    /**\n     * 动画帧回调\n     * \n     * @protected\n     * @method module:util/animation/bezier._$$AnimBezier#__doAnimationFrame\n     * @param  {Number} arg0 - 时间值\n     * @return {Boolean}       是否停止\n     */\n    _pro.__doAnimationFrame = function(_time){\n        var _delta   = _time-this.__begin.time,\n            _percent = this.__doCalCubicBezierAtTime(_delta),\n            _offset  = _u._$fixed(this.__begin.offset*(1-_percent)+\n                                  this.__end.offset*_percent,2),\n            _stop = !1;\n        // offset out of begin and end range\n        if (_delta>=this.__duration){\n            _offset = this.__end.offset;\n            _stop = !0;\n        }\n        this._$dispatchEvent('onupdate',{\n            offset:1*_offset\n        });\n        return _stop;\n    };\n    /**\n     * 取消动画监听事件\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/animation/bezier'\n     * ],function(_t){\n     *     var _easein = nej.ut._$$AnimBezier._$allocate({\n     *         from: {\n     *             offset: 100\n     *         },\n     *         to:{\n     *             offset: 0\n     *         },\n     *         timing:'easein',\n     *         onupdate: function(_event){\n     *             // 坐标\n     *             console.log(_event.offset + 'px');\n     *         }\n     *     });\n     *     // 进行弹性动画\n     *     _easein._$play();\n     *     // 结束动画\n     *     _easein._$stop();\n     * });\n     * ```\n     * @method module:util/animation/bezier._$$AnimBezier#_$stop\n     * @return {Void}\n     */\n    _pro._$stop = function(){\n        this._$dispatchEvent('onupdate',{\n            offset:this.__end.offset\n        });\n        this.__super();\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/animation/bounce.js",
    "content": "/*\n * ------------------------------------------\n * 弹跳动画实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/animation/bounce */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    './animation.js'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 弹跳动画\n     * \n     * 初始信息包括\n     * \n     * * offset    [Number] | 偏移量\n     * * velocity  [Number] | 初速度，单位 px/s\n     *  \n     * 无结束信息\n     * \n     * 脚本举例\n     * ```javascript\n      * NEJ.define([\n     *     'util/animation/bounce'\n     * ],function(_t){\n     *     var _bounce = _t._$$AnimBounce._$allocate({\n     *         from: {\n     *             offset: 100,\n     *             velocity: 100\n     *         },\n     *         acceleration:100,\n     *         onupdate: function(_event){\n     *             // 坐标\n     *             console.log(_event.offset + 'px');\n     *             // 初速度\n     *             console.log(_event.velocity);\n     *         }\n     *     });\n     *     // 进行弹性动画\n     *     _bounce._$play();\n     * });\n     * ```\n     * \n     * @class    module:util/animation/bounce._$$AnimBounce\n     * @extends  module:util/animation/animation._$$Animation\n     * \n     * @param    {Object} config        - 可选配置参数\n     * @property {Number} acceleration  - 加速度，值越小弹跳越快\n     * @property {Number} springtension - 张紧度，0-1之间，值越小弹跳距离越大\n     */\n    _p._$$AnimBounce = _k._$klass();\n    _pro = _p._$$AnimBounce._$extend(_t0._$$Animation);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/animation/bounce._$$AnimBounce#__reset\n     * @param    {Object} arg0 - 可选配置参数\n     * @return   {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__acceleration = _options.acceleration||30;\n        this.__springtension = _options.springtension||0.3;\n    };\n    /**\n     * 动画帧回调\n     * \n     * @protected\n     * @method module:util/animation/bounce._$$AnimBounce#__doAnimationFrame\n     * @param  {Number} arg0 - 时间值\n     * @return {Void}\n     */\n    _pro.__doAnimationFrame = function(_time){\n        var _elapse = _time-this.__begin.time,\n            _factor = _elapse/this.__acceleration,\n            _pwtime = _factor*Math.pow(Math.E,-this.__springtension*_factor),\n            _delta  = this.__begin.velocity*_pwtime,\n            _offset = this.__begin.offset+_delta,\n            _stop = !1;\n        if (_elapse>1&&Math.abs(_delta)<1){\n            _stop = !0;\n            _offset = this.__begin.offset;\n        }\n        this._$dispatchEvent('onupdate',{\n            offset:_offset\n        });\n        return _stop;\n    };\n    /**\n     * 取消动画监听事件\n     * \n     * 脚本举例\n     * ```javascript\n      * NEJ.define([\n     *     'util/animation/bounce'\n     * ],function(_t){\n     *     var _bounce = _t._$$AnimBounce._$allocate({\n     *         from: {\n     *             offset: 100,\n     *             velocity: 100\n     *         },\n     *         acceleration:100,\n     *         onupdate: function(_event){\n     *             // 坐标\n     *             console.log(_event.offset + 'px');\n     *             // 初速度\n     *             console.log(_event.velocity);\n     *         }\n     *     });\n     *     // 进行弹性动画\n     *     _bounce._$play();\n     *     // 停止动画,触发onstop\n     *     _bounce._$stop();\n     * });\n     * ```\n     * \n     * @method module:util/animation/bounce._$$AnimBounce#_$stop\n     * @return {Void}\n     */\n    _pro._$stop = function(){\n        this._$dispatchEvent('onupdate',{\n            offset:this.__begin.offset\n        });\n        this.__super();\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/animation/decelerate.js",
    "content": "/*\n * ------------------------------------------\n * 减速动画实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/animation/decelerate */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    './animation.js'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 减速动画\n     * \n     * 初始信息包括\n     * \n     * * offset    [Number]   偏移量\n     * * velocity  [Number]   初速度，单位 px/s\n     *  \n     * 无结束信息\n     * \n     * 结构举例\n     * ```html\n     * <div id='id-bounce1'></div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/animation/decelerate'\n     * ],function(_t){\n     *     // 创建减速动画实例\n     *     var _decelerate  = _t._$$AnimDecelerate._$allocate({\n     *         from:{\n     *            offset: 100,\n     *             velocity: 10\n     *         },\n     *         onupdate: function(_event){\n     *             // 更新盒子的位置\n     *             _box.style.left = _event.offset + 'px';\n     *         },\n     *         onstop: function(){\n     *             this._$recycle();\n     *         }\n     *     });\n     *     // 开始动画\n     *     _decelerate._$play();\n     * });\n     * ```\n     * \n     * @class    module:util/animation/decelerate._$$AnimDecelerate\n     * @extends  module:util/animation/animation._$$Animation\n     * \n     * @param    {Object} config       - 可选配置参数\n     * @property {Number} friction     - 阻力系数，0-1之间，阻力越大减速距离越短\n     * @property {Number} acceleration - 加速度，值越小减速越快\n     */\n    _p._$$AnimDecelerate = _k._$klass();\n    _pro = _p._$$AnimDecelerate._$extend(_t0._$$Animation);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/animation/decelerate._$$AnimDecelerate#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__friction = _options.friction||0.5;\n        this.__theta = Math.log(1-(this.__friction/10));\n        this.__acceleration = _options.acceleration||30;\n    };\n    /**\n     * 动画帧回调\n     * \n     * @protected\n     * @method module:util/animation/decelerate._$$AnimDecelerate#__doAnimationFrame\n     * @param  {Number}  arg0 - 时间值\n     * @return {Boolean}        是否停止\n     */\n    _pro.__doAnimationFrame = function(_time){\n        var _factor = Math.exp((_time-this.__begin.time)/this.__acceleration*this.__theta),\n            _offset = this.__begin.offset-this.__begin.velocity*(1-_factor)/this.__theta,\n            _velocity = this.__begin.velocity*_factor,\n            _stop = !1;\n        if (Math.abs(_velocity)<=1){\n            _stop = !0;\n        }\n        this._$dispatchEvent('onupdate',{\n            offset:_offset,\n            velocity:_velocity\n        });\n        return _stop;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/animation/demo/easeout.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test easeout animation</title>\n    <meta charset=\"utf-8\"/>\n    <meta name=\"viewport\" content=\"width=device-width,user-scalable=no\">\n    <style>\n      .x{position:absolute;top:50px;left:0;width:50px;height:50px;background:#f00;}\n      .y{top:150px;}\n    </style>\n  </head>\n  <body>\n    <div id=\"xx\" class=\"x\">&nbsp;</div>\n    <div id=\"yy\" class=\"x y\">&nbsp;</div>\n    <script src=\"../../../../src/define.js\"></script>\n    <script>\n      NEJ.define([\n          'base/element',\n          'util/animation/easeout'\n      ],function(_e,_x){\n          \n          var xx = _x._$$AnimEaseOut._$allocate({\n              from:{offset:0},\n              to:{offset:1},\n              duration:500,\n              onupdate:function(_event){\n                  _e._$setStyle(\n                      'xx','left',\n                      _event.offset*600+'px'\n                  );\n              },\n              onstop:function(_event){\n                  this._$recycle();\n              }\n          });\n          xx._$play();\n          \n          var count = 0;\n          function a(){\n              _e._$setStyle(\n                  'yy','left',\n                  (count++)+'px'\n              );\n              window.requestAnimationFrame(a);\n          }\n          window.requestAnimationFrame(a);\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/animation/easein.js",
    "content": "/*\n * ------------------------------------------\n * 先慢后快动画实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/animation/easein */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    './bezier.js'\n],function(NEJ,_k,_u,_t0,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 先慢后快动画\n     * \n     * 结构举例\n     * ```html\n     * <div id='id-bounce1'></div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/animation/easein'\n     * ],function(_t){\n     *     // 创建动画实例\n     *     var _easein  = _t._$$AnimEaseIn._$allocate({\n     *         from:{\n     *             offset:100\n     *         },\n     *         to:{\n     *             offset:200\n     *         },\n     *         duration:1000,\n     *         onupdate:function(_event){\n     *             _box.style.left = _event.offset + 'px';\n     *         },\n     *         onstop:function(){\n     *             this._$recycle();\n     *         }\n     *     });\n     *     // 开始动画\n     *     _easein._$play();\n     * });\n     * ```\n     * \n     * @class   module:util/animation/easein._$$AnimEaseIn\n     * @extends module:util/animation/bezier._$$AnimBezier\n     * \n     * @param   {Object} config 可选配置参数\n     */\n    _p._$$AnimEaseIn = _k._$klass();\n    _pro = _p._$$AnimEaseIn._$extend(_t0._$$AnimBezier);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/animation/easein._$$AnimEaseIn#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        _options = _u._$merge({},_options);\n        _options.timing = 'easein';\n        this.__super(_options);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/animation/easeinout.js",
    "content": "/*\n * ------------------------------------------\n * 先慢后快再慢动画实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/animation/easeinout */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    './bezier.js'\n],function(NEJ,_k,_u,_t0,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 先慢后快再慢动画\n     * \n     * 结构举例\n     * ```html\n     * <div id='id-bounce1'></div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/animation/easeinout'\n     * ],function(_t){\n     *     // 创建动画实例\n     *     var _easeinout  = _t._$$AnimEaseInOut._$allocate({\n     *         from:{\n     *             offset:100\n     *         },\n     *         to:{\n     *             offset:200\n     *         },\n     *         duration:1000,\n     *         onupdate:function(_event){\n     *             _box.style.left = _event.offset + 'px';\n     *         },\n     *         onstop:function(){\n     *             this._$recycle();\n     *         }\n     *     });\n     *     // 开始动画\n     *     _easeinout._$play();\n     * });\n     * ```\n     * \n     * @class   module:util/animation/easeinout._$$AnimEaseInOut\n     * @extends module:util/animation/bezier._$$AnimBezier\n     * \n     * @param   {Object} config 可选配置参数\n     */\n    _p._$$AnimEaseInOut = _k._$klass();\n    _pro = _p._$$AnimEaseInOut._$extend(_t0._$$AnimBezier);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/animation/easeinout._$$AnimEaseInOut#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        _options = _u._$merge({},_options);\n        _options.timing = 'easeinout';\n        this.__super(_options);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/animation/easeout.js",
    "content": "/*\n * ------------------------------------------\n * 先快后慢动画实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/animation/easeout */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    './bezier.js'\n],function(NEJ,_k,_u,_t0,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 先快后慢动画\n     * \n     * 结构举例\n     * ```html\n     * <div id='id-bounce1'></div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/animation/easeout'\n     * ],function(_t){\n     *     // 创建动画实例\n     *     var _easeout  = _t._$$AnimEaseOut._$allocate({\n     *         from:{\n     *             offset:100\n     *         },\n     *         to:{\n     *             offset:200\n     *         },\n     *         duration:1000,\n     *         onupdate:function(_event){\n     *             _box.style.left = _event.offset + 'px';\n     *         },\n     *         onstop:function(){\n     *             this._$recycle();\n     *         }\n     *     });\n     *     // 开始动画\n     *     _easeout._$play();\n     * });\n     * ```\n     * \n     * @class   module:util/animation/easeout._$$AnimEaseOut\n     * @extends module:util/animation/bezier._$$AnimBezier\n     * \n     * @param   {Object} config 可选配置参数\n     */\n    _p._$$AnimEaseOut = _k._$klass();\n    _pro = _p._$$AnimEaseOut._$extend(_t0._$$AnimBezier);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/animation/easeout._$$AnimEaseOut#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        _options = _u._$merge({},_options);\n        _options.timing = 'easeout';\n        this.__super(_options);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/animation/linear.js",
    "content": "/*\n * ------------------------------------------\n * 线性动画实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/animation/linear */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    './bezier.js'\n],function(NEJ,_k,_u,_t0,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 线性动画\n     * \n     * 结构举例\n     * ```html\n     * <div id='id-bounce1'></div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/animation/linear'\n     * ],function(_t){\n     *     // 创建动画实例\n     *     var _linear  = _t._$$AnimLinear._$allocate({\n     *         from:{\n     *             offset:100\n     *         },\n     *         to:{\n     *             offset:200\n     *         },\n     *         duration:1000,\n     *         onupdate:function(_event){\n     *             _box.style.left = _event.offset + 'px';\n     *         },\n     *         onstop:function(){\n     *             this._$recycle();\n     *         }\n     *     });\n     *     // 开始动画\n     *     _linear._$play();\n     * });\n     * ```\n     * \n     * @class   module:util/animation/linear._$$AnimLinear\n     * @extends module:util/animation/bezier._$$AnimBezier\n     * \n     * @param   {Object} config - 可选配置参数\n     */\n    _p._$$AnimLinear = _k._$klass();\n    _pro = _p._$$AnimLinear._$extend(_t0._$$AnimBezier);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/animation/linear._$$AnimLinear#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        _options = _u._$merge({},_options);\n        _options.timing = 'linear';\n        this.__super(_options);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/animation/test/animation.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>animation测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit animation test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<div id=\"id-bounce0\" style=\"width:20px;height:20px;background:red;position:absolute;bottom:120px;\"></div>\n\t\t<div id=\"id-bounce1\" style=\"width:20px;height:20px;background:green;position:absolute;bottom:100px;\"></div>\n\t\t<div id=\"id-bounce2\" style=\"width:20px;height:20px;background:#ccc;position:absolute;bottom:80px;\"></div>\n\t\t<div id=\"id-bounce3\" style=\"width:20px;height:20px;background:#578543;position:absolute;bottom:60px;\"></div>\n\t\t<div id=\"id-bounce4\" style=\"width:20px;height:20px;background:#df3563;position:absolute;bottom:40px;\"></div>\n\t\t<div id=\"id-bounce5\" style=\"width:20px;height:20px;background:#7b21f3;position:absolute;bottom:20px;\"></div>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./animation.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/util/animation/test/animation.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"animation\");\n    \n    //开始单元测试\n    test('正常的测试弹性动画', function() {\n        stop();\n        var _bounce;\n        var _box = document.getElementById('id-bounce0');\n        var options = {\n            from: {\n                offset: 100,\n                velocity: 100\n            },\n            acceleration:100,\n            onupdate: function(offset){\n                _box.style.left = offset.offset + 'px';\n                ok(true,\"成功调用\"+offset.offset);\n            },\n            onstop: function(){\n                _bounce = nej.ut._$$AnimBounce._$recycle(_bounce);\n                start();\n            }\n        }\n        _bounce  = nej.ut._$$AnimBounce._$allocate(options);\n        _bounce._$play();\n    });\n    test('正常的减速动画', function() {\n        stop();\n        var _decelerate;\n        var _box = document.getElementById('id-bounce1');\n        var options = {\n            from:{\n                offset: 100,\n                velocity: 10\n            },\n            onupdate: function(offset){\n                ok(true,\"成功调用\"+offset.offset);\n                _box.style.left = offset.offset + 'px';\n            },\n            onstop: function(){\n                _decelerate = nej.ut._$$AnimDecelerate._$recycle(_decelerate);\n                start();\n            }\n        }\n        _decelerate  = nej.ut._$$AnimDecelerate._$allocate(options);\n        _decelerate._$play();\n    });\n    \n    test('正常的先快后慢动画', function() {\n        stop();\n        var _easeout;\n        var _box = document.getElementById('id-bounce2');\n        var options = {\n            from: {\n                offset: 100,\n                velocity: 10\n            },\n            to: {\n                offset:200\n            },\n            duration:1000,\n            onupdate: function(offset){\n                ok(true,\"成功调用\"+offset.offset);\n                _box.style.left = offset.offset + 'px';\n            },\n            onstop: function(){\n                _easeout = nej.ut._$$AnimEaseOut._$recycle(_easeout);\n                start();\n            }\n        }\n        _easeout  = nej.ut._$$AnimEaseOut._$allocate(options);\n        _easeout._$play();\n    });\n    \n    test('正常的线性动画', function() {\n        stop();\n        var _linear;\n        var _box = document.getElementById('id-bounce3');\n        var options = {\n            from: {\n                offset: 100,\n                velocity: 10\n            },\n            to: {\n                offset:200\n            },\n            duration:1000,\n            onupdate: function(offset){\n                ok(true,\"成功调用\"+offset.offset);\n                _box.style.left = offset.offset + 'px';\n            },\n            onstop: function(){\n                _linear = nej.ut._$$AnimLinear._$recycle(_linear);\n                start();\n            }\n        }\n        _linear  = nej.ut._$$AnimLinear._$allocate(options);\n        _linear._$play();\n    });\n    \n    test('正常的先慢后快动画', function() {\n        stop();\n        var _easein;\n        var _box = document.getElementById('id-bounce4');\n        var options = {\n            from:{\n                offset: 100,\n                velocity: 10\n            },\n            to: {\n                offset:200\n            },\n            duration:1000,\n            onupdate: function(offset){\n                ok(true,\"成功调用\"+offset.offset);\n                _box.style.left = offset.offset + 'px';\n            },\n            onstop: function(){\n                _easein = nej.ut._$$AnimEaseIn._$recycle(_easein);\n                start();\n            }\n        }\n        _easein  = nej.ut._$$AnimEaseIn._$allocate(options);\n        _easein._$play();\n    });\n    \n    test('先慢后快再慢动画实现文件', function() {\n        stop();\n        var _easeinout;\n        var _box = document.getElementById('id-bounce5');\n        var options = {\n            from:{\n                offset: 100,\n                velocity: 10\n            },\n            to: {\n                offset:200\n            },\n            duration:1000,\n            onupdate: function(offset){\n                ok(true,\"成功调用\"+offset.offset);\n                _box.style.left = offset.offset + 'px';\n            },\n            onstop: function(){\n                _easeinout = nej.ut._$$AnimEaseInOut._$recycle(_easeinout);\n                start();\n            }\n        }\n        _easeinout  = nej.ut._$$AnimEaseInOut._$allocate(options);\n        _easeinout._$play();\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}animationTest.js',\n    ['{lib}util/animation/bounce.js','{lib}util/animation/linear.js','{lib}util/animation/decelerate.js',\n    '{lib}util/animation/easeout.js','{lib}util/animation/easein.js','{lib}util/animation/easeinout.js','{pro}log.js'],f);\n});\n  "
  },
  {
    "path": "src/util/audio/audio.js",
    "content": "/**\n * ------------------------------------------\n * 语音接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/audio/audio */\nNEJ.define([\n    'base/global',\n    'base/util',\n    '{platform}audio.js'\n],function(NEJ,_u,_h,_p,_o,_f,_r){\n    /**\n     * 取音频播放器实例\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/audio/audio'\n     * ],function(_e){\n     *     // 取音频播放器实例\n     *     var _audio = _e._$audio({\n     *         preload:false,\n     *         url:'http://127.0.0.1:8000/nej-baseline/res/test.mp3',\n     *         onstatechange:function(_event){\n     *              // 状态改变的回调\n     *              // 0 | 当前停止状态\n     *              // 1 | 当前缓冲状态\n     *              // 2 | 当前播放状态\n     *              // 3 | 当前暂停状态\n     *              // 4 | 播放结束状态\n     *         }\n     *     });\n     *     // 播放\n     *     _audio._$play();\n     *     // 暂停\n     *     _audio._$pause();\n     *     // 停止\n     *     _audio._$stop();\n     * });\n     * ```\n     *\n     * @method module:util/audio/audio._$audio\n     * @param  {Object} arg0 - 配置信息\n     * @return {module:util/media/media._$$Media} 音频播放器实例\n     */\n    _p._$audio = function(_options){\n        return _h.__getAudioInst(_options);\n    };\n    /**\n     * 作为背景播放音频\n     *\n     * 播放状态值说明\n     *\n     * | 状态值 | 说明 |\n     * | :---   | :--- |\n     * | 0 | 当前停止状态 |\n     * | 1 | 当前缓冲状态 |\n     * | 2 | 当前播放状态 |\n     * | 3 | 当前暂停状态 |\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/audio/audio'\n     * ],function(_e){\n     *     // 播放音频\n     *     // 如果之前有音频在播放\n     *     // 则会先触发之前音频的0状态onstatechange事件\n     *     _e._$play(\n     *         'http://a.b.com/a/a.mp3',{\n     *             key:'test-audio'\n     *             extra:'xxx_id',\n     *             onstatechange:function(_event){\n     *                 // _event.state -> 状态值\n     *               // _event.data  -> extra值\n     *             },\n     *             onerror:function(_event){\n     *                 // _event.code  -> 错误类型\n     *             }\n     *         }\n     *     );\n     *     // 停止音频播放\n     *     // 如果有音频在播放\n     *     // 则会触发0状态的onstatechange事件\n     *     _e._$stop('test-audio');\n     * });\n     * ```\n     *\n     * @method   module:util/audio/audio._$play\n     * @param    {String}   arg0          - 音频文件地址\n     * @param    {Object}   arg1          - 可选配置参数\n     * @property {String}   key           - 播放标识，同一标识只允许一个播放实例\n     * @property {Variable} extra         - onstatechange/onerror时传回数据\n     * @property {Number}   retry         - 出错重试次数，0表示不重试，默认为0\n     * @property {Number}   interval      - 如果设置了retry则通过此参数指定每次重试间隔，单位毫秒，默认500\n     * @property {Function} onstatechange - 播放状态变化回调事件，state值见说明\n     * @property {Function} ontimeupdate  - 时间轴变化事件，输入{current:1.000,duration:50.000,data:'extra data'}\n     * @property {Function} onerror       - 播放异常回调事件\n     * @return   {Void}\n     */\n    _p._$play = (function(){\n        // audio player cache\n        // url   - audio url\n        // conf  - play config\n        // audio - audio instance\n        // timer - retry timer\n        var _pcache = {};\n        // callback\n        var _doCallback = function(_key,_name,_event,_cleared){\n            var _cch = _pcache[_key];\n            if (!_cch) return;\n            var _conf = _cch.conf,\n                _func = _conf[_name]||_f,\n                _extr = _conf.extra;\n            if (!!_cleared){\n                delete _pcache[_key];\n            }\n            _event.data = _extr;\n            _func(_event);\n        };\n        // state change callback\n        var _doStateChangeCallback = function(_key,_state){\n            _doCallback(\n                _key,'onstatechange',\n                {state:_state},_state==0\n            );\n        };\n        // error callback\n        var _doErrorCallback = function(_key,_code){\n            _doCallback(_key,'onerror',{code:_code},!0);\n        };\n        // timeupdate callback\n        var _doTimeUpdateCallback = function(_key,_event){\n            _doCallback(_key,'ontimeupdate',_event);\n        };\n        // state change action\n        var _doStateChangeAction = function(_key,_event){\n            if (_event.state==0){\n                _doClearAction(_key);\n            }\n            _doStateChangeCallback(_key,_event.state);\n        };\n        // play action\n        var _doPlayAction = function(_key){\n            var _cch = _pcache[_key];\n            if (!_cch) return;\n            _cch.audio = _h.__getAudioInst({\n                url:_cch.url,\n                onerror:_doErrorAction._$bind(null,_key),\n                ontimeupdate:_doTimeUpdateCallback._$bind(null,_key),\n                onstatechange:_doStateChangeAction._$bind(null,_key)\n            });\n            _cch.audio._$play();\n        };\n        // stop action\n        var _doClearAction = function(_key){\n            var _cch = _pcache[_key];\n            if (!_cch) return;\n            if (!!_cch.audio){\n                _cch.audio = _cch.audio._$recycle();\n            }\n            if (!!_cch.timer){\n                _cch.timer = window.clearTimeout(_cch.timer);\n            }\n        };\n        // error action\n        var _doErrorAction = function(_key,_event){\n            var _cch = _pcache[_key];\n            if (!_cch) return;\n            _doClearAction(_key);\n            var _conf = _cch.conf;\n            if (_conf.retry>0){\n                _conf.retry--;\n                _cch.timer = window.setTimeout(\n                    _doPlayAction._$bind(null,_key),\n                    _conf.interval||500\n                );\n            }else{\n                _doErrorCallback(_key,_event.code);\n            }\n        };\n        /**\n         * 停止单例音频播放\n         * @method module:util/audio/audio._$stop\n         * @see    module:util/audio/audio._$play\n         * @param  {String} arg0 - 播放标识\n         * @return {Void}\n         */\n        _p._$stop = function(_key){\n            var _cch = _pcache[_key||'auto-audio'];\n            if (!!_cch){\n                _cch.audio._$stop();\n            }\n        };\n        return function(_url,_options){\n            if (!_url) return;\n            var _playing = _u._$merge({},_options),\n                _key = _playing.key||'auto-audio',\n                _cch = _pcache[_key];\n            // stop last\n            if (!!_cch){\n                _doClearAction(_key);\n                _doStateChangeCallback(_key,0);\n            }\n            // save audio config\n            _pcache[_key] = {\n                url:_url,\n                conf:_playing\n            };\n            // play current\n            _doPlayAction(_key);\n        };\n    })();\n\n    if (CMPT){\n        var _x = NEJ.P('nej.e');\n        _x._$audio = _p._$audio;\n        _x._$playBgSound = _p._$play;\n        _x._$stopBgSound = _p._$stop;\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/audio/demo/audio.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <title>audio play</title>\n    <meta charset=\"utf-8\"/>\n    <meta name=\"viewport\" content=\"width=device-width,user-scalable=no\">\n</head>\n<body>\n<p>Record</p>\n<input type=\"button\" value=\"play\" id=\"play-rcd\"/>\n<input type=\"button\" value=\"stop\" id=\"stop-rcd\"/>\n<hr/>\n<p>AAC</p>\n<input type=\"button\" value=\"play\" id=\"play-aac\"/>\n<input type=\"button\" value=\"stop\" id=\"stop-aac\"/>\n<hr/>\n<p>AMR</p>\n<input type=\"button\" value=\"play\" id=\"play-amr\"/>\n<input type=\"button\" value=\"stop\" id=\"stop-amr\"/>\n\n<script src=\"../../../../define.js\"></script>\n<script>\n    NEJ.define([\n        'base/event',\n        '../audio.js'\n    ],function(v,a){\n        var rec;\n        v._$addEvent('play-rcd','click',function(){\n            rec = new webkitSpeechRecognition();\n            rec.continuous = true;\n            [\n                'onaudiostart','onsoundstart','onspeechstart',\n                'onspeechend','onsoundend','onaudioend','onresult',\n                'onnomatch','onerror','onstart','onend'\n            ].forEach(function(n){\n                rec[n] = function(ev){\n                    console.log(ev.type);\n                    console.log(ev);\n                }\n            });\n            rec.start();\n        });\n        v._$addEvent('stop-rcd','click',function(){\n            rec.stop();\n        });\n\n        v._$addEvent('play-aac','click',function(){\n            a._$play('./a.aac',{\n                onstatechange:function(event){\n                    console.log(event);\n                }\n            })\n        });\n        v._$addEvent('stop-aac','click',function(){\n            a._$stop();\n        });\n        v._$addEvent('play-amr','click',function(){\n            a._$play('./a.amr',{\n                onstatechange:function(event){\n                    console.log(event);\n                }\n            })\n        });\n        v._$addEvent('stop-amr','click',function(){\n            a._$stop();\n        });\n    });\n</script>\n</body>\n</html>"
  },
  {
    "path": "src/util/audio/platform/audio.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\ndefine([\n    'util/media/audio'\n],function(_t,_p,_o,_f,_r){\n    /**\n     * 取音频播放器实例d\n     * @param  {Object} 配置信息\n     * @return {_$$Media} 音频播放器实例\n     */\n    _p.__getAudioInst = function(_options){\n        return _t._$$MediaAudio._$allocate(_options);\n    };\n\n    return _p;\n});"
  },
  {
    "path": "src/util/audio/platform/audio.patch.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\ndefine([\n    './audio.js'\n],function(_h,_p,_o,_f,_r){\n\t// for ie8-\n\tNEJ.patch('TR<=4.0',['util/media/flash'],function(_t){\n\t    /**\n\t     * 取音频播放器实例d\n\t     * @param  {Object} 配置信息\n\t     * @return {_$$Media} 音频播放器实例\n\t     */\n\t    _h.__getAudioInst = function(_options){\n\t        return _t._$$MediaFlash._$allocate(_options);\n\t    };\n\t});\n\n\treturn _h;\n});"
  },
  {
    "path": "src/util/audio/test/audio.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>audio测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit xdr test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./audio.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/audio/test/audio.test.js",
    "content": "NEJ.define(['util/audio/audio'],function(){\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v');\n    test('audio',function(){\n        expect(0);\n        // _e._$audio(\n        //      {\n        //          key:'test-audio',\n        //          extra:'xxx_id',\n        //          onstatechange:function(_event){\n        //            ok('回调成功' + 'state ' +_event.state +　'data ' + _event.data);\n        //             debugger;\n        //              // _event.state -> 状态值\n        //            // _event.data  -> extra值\n        //            _e._$stopBgSound('test-audio');\n        //            start()\n        //          },\n        //          onerror:function(_event){\n        //              // _event.code  -> 错误类型\n        //          }\n        //      }\n        //  );\n        //  _e._$playBgSound('')\n        var _audio = _e._$audio({\n             preload:true,\n             url:'http://www.zhlongyin.com/UploadFiles/xrxz/2011/5/201105051307513619.mp3',\n             onstatechange:function(_event){\n                   // ok('回调成功' + 'state ' +_event.state +　'data ' + _event.data);\n                   //  debugger;\n                   //  _audio._$pause();\n                   //  // 停止\n                   //  _audio._$stop();\n             }\n         });\n         // 播放\n         _audio._$play();\n    });\n});"
  },
  {
    "path": "src/util/cache/abstract.js",
    "content": "/*\n * ------------------------------------------\n * 列表缓存管理基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/cache/abstract */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    'base/event',\n    'util/ajax/xdr',\n    'util/ajax/rest',\n    'util/ajax/jsonp',\n    './list.js'\n],function(NEJ,_k,_u,_v,_j,_jj,_jjj,_t,_p,_o,_f,_r,_pro){\n    // request config cache\n    var config = {},\n        seed = _u._$uniqueID();\n    /**\n     * 调度事件\n     * @param name\n     * @param event\n     */\n    var dispatch = function(name,event){\n        event = event||{};\n        _u._$forEach(\n            config[name+'-'+seed],function(func){\n                func.call(this,event);\n                if (event.stopped){\n                    return !0;\n                }\n            },this\n        );\n    };\n    /**\n     * 列表缓存管理基类\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/klass',\n     *     'util/ajax/xdr',\n     *     'util/cache/abstract'\n     * ],function(_k,_j,_t,_p){\n     *     // 创建自己的listCache管理类\n     *     _p._$$CacheListCustom = _k._$klass();\n     *     _pro = _p._$$CacheListCustom._$extend(_t._$$CacheListAbstract);\n     *     \n     *     // 实现取列表的方法\n     *     // 根据offset+limit取列表\n     *     // data表示取列表可能需要的额外数据信息\n     *     // 数据返回的回调是onload\n     *     _pro.__doLoadList = function(_options){\n     *         var _key    = _options.key;\n     *         var _data   = _options.data;\n     *         var _offset = _options.offset;\n     *         var _limit  = _options.limit;\n     *         var _rkey   = _options.rkey;\n     *         var _onload = _options.onload;\n     *         _j._$request(\n     *             '/xhr/list',{\n     *                 type:'json',\n     *                 method:'POST',\n     *                 data:{offset:_offset,limit:_limit},\n     *                 timeout:1000,\n     *                 onload:_onload._$bind(this),\n     *                 onerror:function(_error){\n     *                     // TODO\n     *                 }\n     *             }\n     *         );\n     *     };\n     * \n     *     // 实现取列表的方法\n     *     // 根据id和key取一项数据\n     *     // 数据返回的回调是onload\n     *     _proCacheListCustom.__doLoadItem = function(_options){\n     *         var _id     = _options.id;\n     *         var _key    = _options.key;\n     *         var _rkey   = _options.rkey;\n     *         var _onload = _options.onload;\n     *         _j._$request(\n     *             '/xhr/get',{\n     *                 type:'json',\n     *                 method:'POST',\n     *                 data:{id:_id,key:_key},\n     *                 timeout:1000,\n     *                 onload:_onload._$bind(this),\n     *                 onerror:function(_error){\n     *                     // TODO\n     *                 }\n     *             }\n     *         );\n     *     };\n     * });\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     '/path/to/custom/cache.js'\n     * ],function(_p){\n     *     // 实例化一个上面的对象\n     *     var _cache = c._$$CacheListCustom._$allocate({\n     *         // id作为cache的标识\n     *         id:'a',\n     *         // 根据key，也就是上面的id，到缓存中取数据，然后处理数据\n     *         onlistload:function(_ropt){\n     *             _cache._$getListInCache(_ropt.key);\n     *         },\n     *          // 根据key，也就是上面的id，到缓存中取数据，然后处理数据\n     *         onitemload:function(_ropt){\n     *             _cache._$getItemInCache(_ropt.key);\n     *         }\n     *     });\n     * \n     *     // 第一个列表的请求\n     *     _cache._$getList({key:'abc',data:{},offset:0,limit:10})\n     *     // 不会发请求，直接走缓存\n     *     _cache._$getList({key:'abc',data:{},offset:0,limit:10})\n     *     // 第一个项请求\n     *     _cache._$getItem({id:'abc',key:'123',data:{})\n     *     // 不会发请求，直接走缓存\n     *     _cache._$getItem({id:'abc',key:'123',data:{})\n     * });\n     * ```\n     * \n     * @class   module:util/cache/abstract._$$CacheListAbstract\n     * @extends module:util/cache/list._$$CacheList\n     * \n     * @param   {Object} config - 可选配置参数\n     */\n    /** \n     * 列表载入完成回调\n     * \n     * @event    module:util/cache/abstract._$$CacheListAbstract#onlistload\n     * @param    {Object}   event - 可选配置参数\n     * @property {String}   key   - 列表标识\n     * @property {Variable} ext   - 传入数据原样返回\n     */\n    /** \n     * 缓存项载入完成回调\n     * \n     * @event    module:util/cache/abstract._$$CacheListAbstract#onitemload\n     * @param    {Object}   event - 可选配置参数\n     * @property {String}   id    - 项标识\n     * @property {String}   key   - 列表标识\n     * @property {Variable} ext   - 传入数据原样返回\n     */\n    /** \n     * 缓存项添加完成回调\n     * \n     * @event    module:util/cache/abstract._$$CacheListAbstract#onitemadd\n     * @param    {Object}   event - 可选配置参数\n     * @property {String}   id    - 项标识\n     * @property {String}   key   - 列表标识\n     * @property {Variable} ext   - 传入数据原样返回\n     */\n    /** \n     * 缓存项删除完成回调\n     * \n     * @event    module:util/cache/abstract._$$CacheListAbstract#onitemdelete \n     * @param    {Object}   event - 可选配置参数\n     * @property {String}   id    - 项标识\n     * @property {String}   key   - 列表标识\n     * @property {Variable} ext   - 传入数据原样返回\n     */\n    /** \n     * 缓存项更新完成回调\n     * \n     * @event    module:util/cache/abstract._$$CacheListAbstract#onitemupdate\n     * @param    {Object}   event - 可选配置参数\n     * @property {String}   id    - 项标识\n     * @property {String}   key   - 列表标识\n     * @property {Variable} ext   - 传入数据原样返回\n     */\n    /** \n     * 服务器最新列表拉取完成回调\n     * \n     * @event    module:util/cache/abstract._$$CacheListAbstract#onpullrefresh\n     * @param    {Object}   event - 可选配置参数\n     * @property {String}   key   - 列表标识\n     * @property {Variable} ext   - 传入数据原样返回\n     */\n    _p._$$CacheListAbstract = _k._$klass();\n    _pro = _p._$$CacheListAbstract._$extend(_t._$$CacheList);\n    /**\n     * 发送请求\n     *\n     * @protected\n     * @method module:util/cache/abstract._$$CacheListAbstract#__doSendRequest\n     * @param  {String} key - 请求配置标识\n     * @param  {Object} options - 请求信息\n     * @return {Void}\n     */\n    _pro.__doSendRequest = function(key,options){\n        // check config\n        var conf = config[key];\n        if (!conf){\n            console.error('not found request config for '+key);\n            return;\n        }\n        // onerror event\n        var onerror = function(error){\n            var event = {\n                key:key,\n                cnf:conf,\n                req:options,\n                error:error||{}\n            };\n            // check global error handler\n            dispatch.call(this,'error',event);\n            if (event.stopped){\n                return;\n            }\n            // dispatch error config event\n            var onerror = options.onerror||conf.onerror||'onerror';\n            if (_u._$isFunction(onerror)){\n                onerror.call(this,event);\n            }else if(_u._$isString(onerror)){\n                this._$dispatchEvent(onerror,event);\n            }\n        };\n        // onload event\n        var onload = function(result){\n            var event = {\n                req:options,\n                res:result,\n                cnf:conf,\n                key:key\n            };\n            // check post handler\n            if (_u._$isFunction(conf.post)){\n                conf.post.call(this,event);\n            }\n            dispatch.call(this,'post',event);\n            if (!!event.error){\n                onerror.call(this,event.error);\n                return;\n            }\n            // check global format handler\n            if (_u._$isFunction(conf.format)){\n                conf.format.call(this,event);\n            }\n            dispatch.call(this,'format',event);\n            // callback\n            var callback = options.onload||conf.onload;\n            if (event.result!=null){\n                result = event.result;\n            }\n            if (_u._$isFunction(callback)){\n                callback.call(this,result);\n            }else if(_u._$isString(callback)){\n                this._$dispatchEvent(callback,result);\n            }\n            // finally action\n            if (_u._$isFunction(conf.finaly)){\n                conf.finaly.call(this,event);\n            }\n        };\n        // before request\n        var event = {\n            url:conf.url||options.url,\n            req:options,\n            cnf:conf,\n            key:key\n        };\n        dispatch.call(this,'filter',event);\n        if (_u._$isFunction(conf.filter)){\n            conf.filter.call(this,event);\n            // not request if filter has result\n            if (!!event.result){\n                onload.call(this,event.result);\n                return;\n            }\n        }\n        // send request\n        var opt = _u._$merge({},options,{\n            type:conf.type||'json',\n            method:conf.method||'POST',\n            onload:onload._$bind(this),\n            onerror:onerror._$bind(this)\n        });\n        // do request\n        var _req = _j;\n        if (conf.rest){\n            _req = _jj;\n        }\n        if (conf.jsonp){\n            _req = _jjj;\n        }\n        _req._$request(event.url,opt);\n    };\n    /**\n     * 控件初始化\n     * \n     * @protected\n     * @method module:util/cache/abstract._$$CacheListAbstract#__init\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this._$batEvent({\n            doloadlist:this.__doLoadList._$bind(this),\n            doloaditem:this.__doLoadItem._$bind(this),\n            doadditem:this.__doAddItem._$bind(this),\n            dodeleteitem:this.__doDeleteItem._$bind(this),\n            doupdateitem:this.__doUpdateItem._$bind(this),\n            dopullrefresh:this.__doPullRefresh._$bind(this)\n        });\n    };\n    /**\n     * 从服务器端载入列表，子类实现具体逻辑\n     * \n     * @abstract\n     * @method   module:util/cache/abstract._$$CacheListAbstract#__doLoadList\n     * @param    {Object}   arg0   - 请求信息\n     * @property {String}   key    - 列表标识\n     * @property {Number}   offset - 偏移量\n     * @property {Number}   limit  - 数量\n     * @property {String}   data   - 请求相关数据\n     * @property {Function} onload - 列表项载入回调\n     * @return   {Void}\n     */\n    _pro.__doLoadList = _f;\n    /**\n     * 从服务器端前向刷新列表，子类实现具体逻辑\n     * \n     * @abstract\n     * @method   module:util/cache/abstract._$$CacheListAbstract#__doPullRefresh\n     * @param    {Object}   arg0   - 请求信息\n     * @property {String}   key    - 列表标识\n     * @property {String}   data   - 请求相关数据\n     * @property {Function} onload - 列表项载入回调\n     * @return   {Void}\n     */\n    _pro.__doPullRefresh = _f;\n    /**\n     * 从服务器端载入列表项，子类实现具体逻辑\n     * \n     * @abstract\n     * @method   module:util/cache/abstract._$$CacheListAbstract#__doLoadItem\n     * @param    {Object}   arg0   - 请求信息\n     * @property {String}   key    - 列表标识\n     * @property {Number}   id     - 列表项标识\n     * @property {String}   data   - 请求相关数据\n     * @property {Function} onload - 列表项载入回调\n     * @return   {Void}\n     */\n    _pro.__doLoadItem = _f;\n    /**\n     * 添加列表项至服务器，子类实现具体逻辑\n     * \n     * @abstract\n     * @method   module:util/cache/abstract._$$CacheListAbstract#__doAddItem\n     * @param    {Object}   arg0   - 请求信息\n     * @property {String}   key    - 列表标识\n     * @property {Number}   id     - 列表项标识\n     * @property {String}   data   - 请求相关数据\n     * @property {Function} onload - 列表项载入回调\n     * @return   {Void}\n     */\n    _pro.__doAddItem = _f;\n    /**\n     * 从服务器上删除列表项，子类实现具体逻辑\n     * \n     * @abstract\n     * @method    module:util/cache/abstract._$$CacheListAbstract#__doDeleteItem\n     * @param     {Object}   event  - 请求信息\n     * @property  {String}   key    - 列表标识\n     * @property  {Number}   id     - 列表项标识\n     * @property  {String}   data   - 请求相关数据\n     * @property  {Function} onload - 列表项载入回调\n     * @return    {Void}\n     */\n    _pro.__doDeleteItem = _f;\n    /**\n     * 更新列表项至服务器，子类实现具体逻辑\n     * \n     * @abstract\n     * @method module:util/cache/abstract._$$CacheListAbstract#__doUpdateItem\n     * @param    {Object}   event  - 请求信息\n     * @property {String}   key    - 列表标识\n     * @property {Number}   id     - 列表项标识\n     * @property {String}   data   - 请求相关数据\n     * @property {Function} onload - 列表项载入回调\n     * @return   {Void}\n     */\n    _pro.__doUpdateItem = _f;\n    /**\n     * 全局预处理事件配置\n     *\n     * @param  {Object}   map - 事件配置信息\n     * @param  {function} map.filter - 请求发送之前统一预处理事件，输入为{req:options,url:'url'}\n     * @param  {function} map.post   - 请求返回之后统一预处理事件，输入为{req:options,res:result}\n     * @param  {function} map.format - 请求返回数据统一格式化事件, 输入为{req:options,res:result}\n     * @param  {function} map.error  - 请求返回异常统一预处理事件, 输入为{req:options,error:error}\n     * @return {Void}\n     */\n    _p._$on = (function(){\n        var _doAdd = function(name,func){\n            if (!_u._$isFunction(func)){\n                return;\n            }\n            var key = name+'-'+seed,\n                list = config[key]||[];\n            list.push(func);\n            config[key] = list;\n        };\n        return function(map){\n            // for name and func\n            if (_u._$isString(map)){\n                _doAdd.apply(null,arguments);\n                return;\n            }\n            // for batch add\n            _u._$loop(map,function(func,key){\n                _doAdd(key,func);\n            });\n        };\n    })();\n    /**\n     * 执行缓存的同步方法，执行完毕后立即回收缓存\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'base/klass',\n     *     'util/cache/abstract'\n     * ],function(k,t,p,pro){\n     *     // 定义自己的缓存类\n     *     p._$$Cache = k._$klass();\n     *     pro = p._$$Cache._$extend(t._$$CacheListAbstract);\n     *\n     *     // 对外接口\n     *     pro._$getDataForCheck = function(){\n     *         // TODO something\n     *         return 'result';\n     *     }\n     *\n     *     // 重写_$do方法，绑定缓存构造器\n     *     p._$do = t._$do._$bind(\n     *         null,p._$$Cache\n     *     );\n     * });\n     * ```\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'path/to/cache'\n     * ],function(t){\n     *\n     *     // 使用缓存\n     *     var ret = t._$do(function(cache){\n     *         return cache._$getDataForCheck();\n     *     });\n     *\n     *     // TODO something\n     * }\n     * ```\n     *\n     * @method module:util/cache/abstract._$do\n     * @param  {Function} Klass - 缓存构造器\n     * @param  {function} func  - 执行回调\n     * @return {Variable} 回调返回结果\n     */\n    _p._$do = function(Klass,func){\n        if (!_u._$isFunction(func)){\n            return;\n        }\n        var cache = Klass._$allocate(),\n            ret = func.call(null,cache);\n        cache._$recycle();\n        return ret;\n    };\n    /**\n     * 请求配置信息，项目中可以统一配置请求信息，可配置项如下表所示\n     *\n     * | 名称    | 类型     | 描述  |\n     * | :----:  | :----:   | :---- |\n     * | url     | String   | 请求地址 |\n     * | method  | String   | 请求方式，GET/POST/PUT等，默认为POST |\n     * | rest    | Boolean  | 是否REST接口 |\n     * | filter  | Function | 请求发送之前配置信息过滤接口 |\n     * | post    | Function | 请求返回之后结果检查接口 |\n     * | format  | Function | 请求返回结果格式化接口 |\n     * | finaly  | Function | 回调结束后执行业务逻辑接口 |\n     * | onerror | Function | 异常处理接口 |\n     * | onload  | Function | 回调处理接口 |\n     *\n     * @method module:util/cache/abstract._$config\n     * @see    module:util/cache/abstract._$on\n     * @param  {Object} map - 配置映射关系，如{'key1':{url:'url'},'key2':'url'}\n     * @return {Void}\n     */\n    _p._$config = function(map){\n        _u._$forIn(map,function(value,key){\n            if (typeof value==='string'){\n                value = {url:value};\n            }\n            config[key] = value;\n        });\n    };\n    /**\n     * 合并请求配置信息\n     *\n     * @method module:util/cache/abstract._$merge\n     * @see    module:util/cache/abstract._$config\n     * @param  {String} key - 配置标识\n     * @param  {Object} map - 配置信息\n     * @return {Void}\n     */\n    _p._$merge = function(key,map){\n        var conf = config[key];\n        if (!conf){\n            config[key] = map;\n        }else{\n            config[key] = _u._$merge(conf,map);\n        }\n    };\n\n    /**\n     * 导出配置信息对象\n     *\n     * @method module:util/cache/abstract._$dump\n     * @returns {Object} 配置信息对象\n     */\n    _p._$dump = function(){\n        return config;\n    };\n\n    if (CMPT){\n        NEJ.P('nej.ut')._$$AbstractListCache = _p._$$CacheListAbstract;\n    }\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/cache/cache.js",
    "content": "/*\n * ------------------------------------------\n * 缓存管理基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/cache/cache */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    'util/event',\n    './storage.js'\n],function(NEJ,_k,_u,_t,_j,_p,_o,_f,_r){\n    var _pro,\n        _ckey = 'dat-'+(+new Date);\n    /**\n     * 缓存对象基类\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/klass',\n     *     'util/ajax/xdr',\n     *     'util/cache/cache'\n     * ],function(_k,_j,_t,_p){\n     *     var _pro;\n     * \n     *     _p._$$CacheCustom = _k._$klass();\n     *     _pro = _p._$$CacheCustom._$extend(_t._$$CacheAbstract);\n     * \n     *     // 取缓存数据，先从内存中取，没有从服务器上取\n     *     _pro._$getDataInCache = function(_key){\n     *         this.__setDataInCache(_key,_value);\n     *     };\n     * \n     *     // 取数据\n     *     _pro._$getData = function(_key){\n     *         var _data = this._$getDataInCache(_key);\n     *         // 数据已在缓存中\n     *         if (_data!=null){\n     *             this._$dispatchEvent('ondataload',{\n     *                 key:_key\n     *             });\n     *             return;\n     *         }\n     *         // 从服务器端载入数据\n     *         // rkey为请求唯一标识，可以是URL，也可以是某种算法的结果\n     *         var _rkey = this.__doGenReqKey(_key), \n     *             _callback = this._$dispatchEvent._$bind(\n     *                 this,'ondataload',{key:_key}\n     *             );\n     *         if (!this.__doQueueRequest(_rkey,_callback)){\n     *             _j._$request({\n     *                 onload:function(_data){\n     *                     // 缓存数据\n     *                     this.__setDataInCache(_key,_data);\n     *                     // 触发队列中同请求的回调逻辑\n     *                     this.__doCallbackRequest(_rkey);\n     *                 }._$bind(this)\n     *             });\n     *         }\n     *     };\n     * \n     *     return _p;\n     * });\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       '/path/to/custom/cache.js'\n     *   ],function(_p){\n     *       // 使用Cache\n     *       var _cache = _p._$$CacheCustom._$allocate({\n     *           ondataload:function(_event){\n     *               // get data in cache\n     *               var _data = this._$getDataInCache(_event.key);\n     *               // TODO \n     *           }\n     *       });\n     *       // 第一个请求\n     *       _cache._$getData('a');\n     *       // 第二个请求\n     *       _cache._$getData('b');、\n     *       // 不会发请求，直接走缓存\n     *       _cache._$getData('a');\n     *   });\n     * ```\n     * \n     * @class   module:util/cache/cache._$$CacheAbstract \n     * @extends module:util/event._$$EventTarget\n     * \n     * @param   {Object} config - 配置参数\n     */\n    _p._$$CacheAbstract = _k._$klass();\n    _pro = _p._$$CacheAbstract._$extend(_t._$$EventTarget);\n    /**\n     * 初始化函数\n     * \n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__super();\n        this.__cache = this.constructor[_ckey];\n        if (!this.__cache){\n            this.__cache = {};\n            // request loading information\n            this.__cache[_ckey+'-l'] = {};\n            this.constructor[_ckey] = this.__cache;\n        }\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__doClearReqFromQueue();\n        this.__super();\n    };\n    /**\n     * 从缓存中取数据\n     * \n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__getDataInCache\n     * @param  {String}   arg0 - 缓存键值\n     * @return {Variable}        缓存数据\n     */\n    _pro.__getDataInCache = function(_key){\n        return this.__cache[_key];\n    };\n    /**\n     * 数据存入缓存\n     * \n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__setDataInCache\n     * @param  {String}   arg0 - 缓存键值\n     * @param  {Variable} arg1 - 缓存数据\n     * @return {Void}\n     */\n    _pro.__setDataInCache = function(_key,_value){\n        this.__cache[_key] = _value;\n    };\n    /**\n     * 带默认值取本地数据\n     * \n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__getDataInCacheWithDefault\n     * @param  {String}   arg0 - 键值\n     * @param  {Variable} arg1 - 默认值\n     * @return {Void}\n     */\n    _pro.__getDataInCacheWithDefault = function(_key,_default){\n        var _data = this.__getDataInCache(_key);\n        if (_data==null){\n            _data = _default;\n            this.__setDataInCache(_key,_data);\n        }\n        return _data;\n    };\n    /**\n     * 删除缓存数据，不传键值则清除所有缓存\n     * \n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__delDataInCache\n     * @param  {String} arg0 - 缓存键值\n     * @return {Void}\n     */\n    _pro.__delDataInCache = function(_key){\n        if (_key!=null){\n            delete this.__cache[_key];\n            return;\n        }\n        _u._$loop(\n            this.__cache,function(_item,_key){\n                if (_key!=(_ckey+'-l')){\n                    this.__delDataInCache(_key);\n                }\n            },this\n        );\n    };\n    /**\n     * 从本地存储中删除数据\n     * \n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__delDataInStorage\n     * @param  {String} arg0 - 存储键值\n     * @return {String}        存储数据\n     */\n    _pro.__delDataInStorage = function(_key){\n        return _j._$delDataInStorage(_key);\n    };\n    /**\n     * 从本地存储中取数据\n     * \n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__getDataInStorage\n     * @param  {String} arg0 - 存储键值\n     * @return {String}        存储数据\n     */\n    _pro.__getDataInStorage = function(_key){\n        return _j._$getDataInStorage(_key);\n    };\n    /**\n     * 数据存入本地缓存\n     * \n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__setDataInStorage\n     * @param  {String}   arg0 - 存储键值\n     * @param  {Variable} arg1 - 存储数据\n     * @return {Void}\n     */\n    _pro.__setDataInStorage = function(_key,_value){\n        _j._$setDataInStorage(_key,_value);\n    };\n    /**\n     * 带默认值取本地数据\n     * \n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__getDataLocalWithDefault\n     * @param  {String}   arg0 - 键值\n     * @param  {Variable} arg1 - 默认值\n     * @return {Variable}        数据\n     */\n    _pro.__getDataLocalWithDefault = function(_key,_default){\n        var _data = this.__getDataLocal(_key);\n        if (_data==null){\n            _data = _default;\n            this.__setDataLocal(_key,_data);\n        }\n        return _data;\n    };\n    /**\n     * 取本地数据,检测内存和本地存储\n     * \n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__getDataLocal\n     * @param  {String}   arg0 - 键值\n     * @return {Variable}        数据\n     */\n    _pro.__getDataLocal = function(_key){\n        // get from memory\n        var _data = this.__getDataInCache(_key);\n        if (_data!=null){\n            return _data;\n        }\n        // get from storage\n        _data = this.__getDataInStorage(_key);\n        if (_data!=null){\n            this.__setDataInCache(_key,_data);\n        }\n        return _data;\n    };\n    /**\n     * 存本地数据\n     * \n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__setDataLocal\n     * @param  {String}   arg0 - 键值\n     * @param  {Variable} arg1 - 数据\n     * @return {Void}\n     */\n    _pro.__setDataLocal = function(_key,_value){\n        this.__setDataInStorage(_key,_value);\n        this.__setDataInCache(_key,_value);\n    };\n    /**\n     * 清除本地缓存，不传键值则清除所有缓存\n     * \n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__delDataLocal\n     * @param  {String} arg0 - 缓存键值\n     * @return {Void}\n     */\n    _pro.__delDataLocal = function(_key){\n        if (_key!=null){\n            delete this.__cache[_key];\n            _j._$delDataInStorage(_key);\n            return;\n        }\n        _u._$loop(\n            this.__cache,function(_item,_key){\n                if (_key!=(_ckey+'-l')){\n                    this.__delDataLocal(_key);\n                }\n            },this\n        );\n    };\n    /**\n     * 清除缓存数据\n     * \n     * 脚本举例\n     * ```javascript\n     * var _cache = new c._$$CacheAbstract();\n     * j._$clearDataLocal('name','jack');\n     * // 清空所有hash值\n     * j._$clearDataInStorage();\n     * ```\n     * \n     * @method module:util/cache/cache._$$CacheAbstract#_$clearDataLocal\n     * @return {Void}\n     */\n    _pro._$clearDataLocal = function(){\n        this.__delDataLocal();\n    };\n    /**\n     * 请求回调\n     * \n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__doCallbackRequest\n     * @param  {String} arg0 - 请求标识\n     * @return {Void}\n     */\n    _pro.__doCallbackRequest = function(_key){\n        var _data = this.__cache[_ckey+'-l'],\n            _args = _r.slice.call(arguments,1);\n        _u._$forEach(\n            _data[_key],function(_callback){\n                try{\n                    _callback.apply(this,_args);\n                }catch(ex){\n                    // ignore\n                    if (DEBUG) throw ex;\n                    console.error(ex.message);\n                    console.error(ex.stack);\n                }\n            }\n        );\n        delete _data[_key];\n    };\n    /**\n     * 锁定请求，同样的请求只发送一次\n     * \n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__doQueueRequest\n     * @param  {String}   arg0 - 请求标识\n     * @param  {Function} arg1 - 请求回调\n     * @return {Boolean}         是否已存在相同请求\n     */\n    _pro.__doQueueRequest = function(_key,_callback){\n        // cache to clear list\n        if (!this.__qtmp){\n            this.__qtmp = [];\n        }\n        this.__qtmp.push({\n            key:_key,\n            callback:_callback\n        });\n        // check request queue list\n        _callback = _callback||_f;\n        var _list = this.__cache[_ckey+'-l'][_key];\n        if (!_list){\n            _list = [_callback];\n            this.__cache[_ckey+'-l'][_key] = _list;\n            return !1;\n        }\n        _list.push(_callback);\n        return !0;\n    };\n    /**\n     * 从请求队列中移除回调\n     *\n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__doClearReqFromQueue\n     * @return {Void}\n     */\n    _pro.__doClearReqFromQueue = function(){\n        _u._$forEach(this.__qtmp,function(it){\n            var _xlist = this.__cache[_ckey+'-l'][it.key];\n            _u._$reverseEach(\n                _xlist,function(item,index,list){\n                    if (item===it.callback){\n                        list.splice(index);\n                    }\n                }\n            );\n            if (!_xlist||!_xlist.length){\n                this.__doClearReqQueue(it.key);\n            }\n        },this);\n        delete this.__qtmp;\n    };\n    /**\n     * 清除锁定请求\n     *\n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__doClearReqQueue\n     * @param  {String}   arg0 - 请求标识\n     * @return {Void}\n     */\n    _pro.__doClearReqQueue = function(_key){\n        delete this.__cache[_ckey+'-l'][_key];\n    };\n\n    /**\n     * 判断列表项是否未定义，子类可根据实际情况重写判断逻辑\n     *\n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__isItemUndefined\n     * @param  {Object}  arg0 - 列表项\n     * @return {Boolean} 是否未定义\n     */\n    _pro.__isItemUndefined = function (item) {\n        return item===undefined;\n    };\n\n    /**\n     * 检测列表中是否已存在指定片段数据\n     * \n     * @protected\n     * @method module:util/cache/cache._$$CacheAbstract#__hasFragment\n     * @param  {Array}   arg0 - 列表\n     * @param  {Number}  arg1 - 偏移量\n     * @param  {Number}  arg2 - 数量，0表示全列表，默认为0\n     * @return {Boolean}        是否已经存在\n     */\n    _pro.__hasFragment = function(_list,_offset,_limit){\n        if (!_list) return !1;\n        _offset = parseInt(_offset)||0;\n        _limit  = parseInt(_limit)||0;\n        if (!_limit){\n            if (!_list.loaded){\n                return !1;\n            }\n            _limit = _list.length;\n        }\n        // length is list total number\n        if (!!_list.loaded){\n            _limit = Math.min(_limit,_list.length-_offset);\n        }\n        for(var i=0;i<_limit;i++){\n            if (this.__isItemUndefined(_list[_offset+i])){\n                return !1;\n            }\n        }\n        return !0;\n    };\n    /**\n     * 判断列表指定片段是否填充满的\n     *\n     * @method module:util/cache/cache._$$CacheAbstract#_$isFragmentFilled\n     * @param  {Array}   arg0 - 列表标识\n     * @param  {Number}  arg1 - 偏移量\n     * @param  {Number}  arg2 - 数量，0表示全列表，默认为0\n     * @return {Boolean}        是否已经存在\n     */\n    _pro._$isFragmentFilled = function(_key,_offset,_limit){\n        return this.__hasFragment(\n            this._$getListInCache(_key),\n            _offset,_limit\n        );\n    };\n    \n    if (CMPT){\n        NEJ.P('nej.ut')._$$Cache = _p._$$CacheAbstract;\n    }\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/cache/cache.list.base.js",
    "content": "// link to util/cache/abstract for compatible\n// use util/cache/abstract for new project\nNEJ.define(['./abstract.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/cache/cache.list.js",
    "content": "// link to util/cache/list for compatible\n// use util/cache/list for new project\nNEJ.define(['./list.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/cache/cache.share.js",
    "content": "// link to util/cache/share for compatible\n// use util/cache/share for new project\nNEJ.define(['./share.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/cache/cookie.js",
    "content": "/*\n * ------------------------------------------\n * COOKIE操作接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/cache/cookie */\nNEJ.define([\n    'base/global',\n    'base/util'\n],function(NEJ,_u,_p,_o,_f,_r){\n    /**\n     * 设置或者获取cookie\n     *\n     * * 没有输入第二个参数则表示返回已有cookie\n     * * 如果cookie值为空字符串则表示删除cookie\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'util/cookie'\n     *   ],function(_j){\n     *       // 设置cookie的name=abc\n     *       var _cookie = _j._$cookie('name','abc');\n     *       _j._$cookie('name',{value:'abc'});\n     *\n     *       // 设置路径，domain(如果domain不同域，cookie设置不会成功),设置过期时间1天;\n     *       var _cookie = _j._$cookie('name',{\n     *           value:'abc',\n     *           path:'/a/',\n     *           domain:'www.163.com',\n     *           expires:1\n     *       });\n     *\n     *       // 删除cookie\n     *       _j._$cookie('name','');\n     *       _j._$cookie('name',{expires:-1});\n     *   });\n     * ```\n     *\n     * @method   module:util/cache/cookie._$cookie\n     * @param    {String}        arg0    - cookie名称\n     * @param    {String|Object} arg1    - cookie值，如果有其他配置信息输入对象，已处理属性包括\n     * @property {String}        value   - cookie值\n     * @property {String}        path    - 路径\n     * @property {String}        domain  - 域名，当前域或者当前域的父域\n     * @property {Number}        expires - 过期时间偏移，单位天，负值表示删除cookie\n     * @return   {String}                  cookie值\n     */\n    _p._$cookie = (function(){\n        var _date = new Date(),\n            _crut = +_date,   // current time milliseconds\n            _days = 86400000; // milliseconds of one day\n        var _getcookie = function(_name){\n            var _cookie = document.cookie,\n                _search = '\\\\b'+_name+'=',\n                _index1 = _cookie.search(_search);\n            if (_index1<0) return '';\n            _index1 += _search.length-2;\n            var _index2 = _cookie.indexOf(';',_index1);\n            if (_index2<0) _index2 = _cookie.length;\n            return _cookie.substring(_index1,_index2)||'';\n        };\n        return function(_name,_data){\n            if (_data===undefined){\n                return _getcookie(_name);\n            }\n            if (_u._$isString(_data)){\n                if (!!_data){\n                    document.cookie = _name+'='+_data+';';\n                    return _data;\n                }\n                _data = {expires:-100};\n            }\n            _data = _data||_o;\n            var _cookie = _name+'='+(_data.value||'')+';';\n            delete _data.value;\n            if (_data.expires!==undefined){\n                _date.setTime(_crut+_data.expires*_days);\n                _data.expires = _date.toGMTString();\n            }\n            _cookie += _u._$object2string(_data,';');\n            //console.log(_cookie);\n            document.cookie = _cookie;\n        };\n    })();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.j'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/cache/database.js",
    "content": "/*\n * ------------------------------------------\n * IndexedDB数据库管理器实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/cache/database */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    'util/event',\n    'base/chain'\n],function(NEJ,_k,_u,_t,_x,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * IndexedDB数据库管理器\n     *\n     * 代码举例：\n     * ```javascript\n     * NEJ.define([\n     *     'util/cache/database'\n     * ],function(_t){\n     *     // 使用控件取数据\n     *     var _db = _t._$$DataBase._$allocate({\n     *         namespace:'music.track'\n     *     });\n     *     _db._$get([1,2,3],{\n     *         onload:function(_result){\n     *             // result ->\n     *             // [{id:1,...},{id:2,...},{id:3,...}]\n     *         }\n     *     });\n     *\n     *     // 使用API取数据\n     *     _t._$requestByDB({\n     *         namespace:'music.track',\n     *         action:'get',\n     *         param:[1,2,3],\n     *         onload:function(_result){\n     *             // result ->\n     *             // [{id:1,...},{id:2,...},{id:3,...}]\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @class    module:util/cache/database._$$DataBase\n     * @extends  module:util/event._$$EventTarget\n     *\n     * @param    {Object} config    - 配置参数\n     * @property {String} namespace - 名字空间，默认随机生成，格式[DB].[TB]，如 music.track\n     * @property {Number} version   - 版本信息，默认使用时间戳作为版本，必须确保在新的namespace下给的version是递增的\n     * @property {String} key       - 标识字段名，默认为id\n     */\n    /**\n     * 数据库准备完成回调\n     *\n     * @event    module:util/cache/database._$$DataBase#onready\n     * @param    {Object}                                 event  - 数据库信息\n     * @property {module:util/cache/database._$$DataBase} target - 数据库实例\n     */\n    /**\n     * 数据库操作失败回调\n     *\n     * @event    module:util/cache/database._$$DataBase#onerror\n     * @param    {Object} event   - 错误信息\n     * @property {Number} code    - 错误代码\n     * @property {String} message - 错误描述\n     */\n    _p._$$DataBase = _k._$klass();\n    _pro = _p._$$DataBase._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/cache/database._$$DataBase#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = (function(){\n        var _doUpgrade = function(_event){\n            //console.log('Upgrade -> '+this.__tbname);\n            var _db = _event.target.result;\n            this.__database = _db;\n            var _index = _u._$indexOf(\n                _db.objectStoreNames,\n                this.__tbname\n            );\n            if (_index>=0) return;\n            _db.createObjectStore(\n                this.__tbname,\n                {keyPath:this.__key}\n            );\n        };\n        var _doDBOpened = function(_event){\n            //console.log('Success -> '+this.__tbname);\n            this.__database = _event.target.result;\n            this._$dispatchEvent('onready',{target:this});\n            // flush action queue\n            _u._$forEach(\n                this.__queue,function(_handler){\n                    _handler.call(this);\n                },this\n            );\n            delete this.__queue;\n        };\n        return function(_options){\n            this.__super(_options);\n            var _arr = (_options.namespace||'').split('.'),\n                _dbname = _arr[0]||('db-'+_u._$uniqueID());\n            this.__tbname = _arr[1]||('tb-'+_u._$uniqueID());\n            this.__key = _options.key||'id';\n            // open database\n            var _request = indexedDB.open(\n                _dbname,_options.version||_u._$uniqueID()\n            );\n            _request.onsuccess = _doDBOpened._$bind(this);\n            _request.onupgradeneeded = _doUpgrade._$bind(this);\n        };\n    })();\n    /**\n     * 控件回收\n     *\n     * @protected\n     * @method module:util/cache/database._$$DataBase#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__dbname;\n        delete this.__tbname;\n        delete this.__queue;\n        delete this.__key;\n        if (!!this.__database){\n            this.__database.close();\n            delete this.__database;\n        }\n    };\n    /**\n     * 判断数据库是否已经准备好\n     *\n     * @protected\n     * @method module:util/cache/database._$$DataBase#__isDBReady\n     * @return {Boolean} 是否已经准备好\n     */\n    _pro.__isDBReady = function(_method,_args){\n        if (!this.__database){\n            if (!this.__queue)  this.__queue = [];\n            var _argc = _r.slice.call(_args,0)||[];\n            _argc.unshift(this);\n            this.__queue.push(\n                _method._$bind.apply(_method,_argc)\n            );\n            return !1;\n        }\n        return !0;\n    };\n    /**\n     * 取存储操作对象\n     *\n     * @protected\n     * @method module:util/cache/database._$$DataBase#__getTransaction\n     * @param  {Object}  arg0 - 配置信息\n     * @return {IDBObjectStore} 存储操作对象\n     */\n    _pro.__getTransaction = function(_options){\n        _options = _options||_o;\n        var _tx = this.__database.transaction(\n            this.__tbname,\n            _options.mode||'readwrite'\n        );\n        _u._$loop(\n            _options,function(_func,_key){\n                if (_u._$isFunction(_func)){\n                    _tx[_key] = _func;\n                }\n            },this\n        );\n        return _tx.objectStore(this.__tbname);\n    };\n    /**\n     * 执行某个操作\n     *\n     * @protected\n     * @method   module:util/cache/database._$$DataBase#__doAction\n     * @param    {String}       arg0    - 操作名称，如put/delete\n     * @param    {Object|Array} arg1    - 操作的数据信息\n     * @property {Function}     onload  - 成功回调\n     * @property {Function}     onerror - 失败回调，输入结构{code:xxx,message:'xxxx'}\n     * @return   {Void}\n     */\n    _pro.__doAction = function(_action,_hash,_options){\n        var _ready = this.__isDBReady(\n            this.__doAction,arguments\n        );\n        if (!_ready) return;\n        // insert records\n        _options = _options||_o;\n        var _error;\n        var _tx = this.__getTransaction({\n            oncomplete:function(_event){\n                if (!_error){\n                    (_options.onload||_f)();\n                }else{\n                    (_options.onerror||_f)(_error);\n                }\n            },\n            onerror:function(_event){\n                // rollback\n                _error = _event.target.error;\n                _event.preventDefault();\n            }\n        });\n        _u._$loop(_hash,function(_item){\n            if (_item!=null){\n                //console.log('do '+_action+' -> '+_item);\n                _tx[_action](_item);\n            }\n        });\n    };\n    /**\n     * 异步取指定键的数据信息\n     *\n     * 脚本举例\n     * ```javascript\n     * // 取单个数据对象\n     * _db._$get('1234568',{\n     *     onload:function(_data){\n     *         // 数据对象\n     *     },\n     *     onerror:function(_error){\n     *         // _error.code\n     *         // _error.message\n     *     }\n     * });\n     *\n     * // 取一批数据，以Map形式返回结果\n     * _db._$get({'123':null,'234':null,...},{\n     *     onload:function(_map){\n     *         // _map ->\n     *         // {'123':{...},'234':{...}}\n     *     },\n     *     onerror:function(_error){\n     *         // 同上\n     *     }\n     * });\n     *\n     * // 取一批数据，以数组形式返回结果\n     * _db._$get(['123','234',...]},{\n     *     onload:function(_result){\n     *         // _result ->\n     *         // [{...},{...},{...}]\n     *     },\n     *     onerror:function(_error){\n     *         // 同上\n     *     }\n     * });\n     * ```\n     *\n     * @method   module:util/cache/database._$$DataBase#_$get\n     * @param    {String|Object|Array} arg0   - 指定数据的键\n     * @param    {Object}              arg1   - 其他配置信息\n     * @property {Function}            onload - 成功获取回调，输入集合类型同传入参数类型一致\n     * @return   {Void}\n     */\n    _pro._$get = (function(){\n        var _doLoadBatchData = function(_store,_map,_onload){\n            var _count = 0;\n            _u._$loop(\n                _map,function(_value,_key){\n                    _count++;\n                    _doLoadData(\n                        _store,_key,\n                        function(_data,_key){\n                            _count--;\n                            _map[_key] = _data;\n                            if (!_count){\n                                _onload(_map);\n                            }\n                        }\n                    );\n                }\n            );\n            if (!_count){\n                _onload(_map);\n            }\n        };\n        var _doLoadData = function(_store,_key,_onload){\n            var _req = _store.get(_key);\n            _req.onsuccess = function(_event){\n                _onload(_event.target.result||null,_key);\n            };\n            _req.onerror = function(_event){\n                _onload(null,_key);\n            };\n        };\n        return function(_keys,_options){\n            var _ready = this.__isDBReady(\n                this._$get,arguments\n            );\n            if (!_ready) return;\n            // do get\n            var _store = this.__getTransaction(_options),\n                _onload = (_options||_o).onload||_f;\n            if (_u._$isArray(_keys)){\n                var _map = _u._$array2object(_keys);\n                _doLoadBatchData(_store,_map,function(_map){\n                    var _arr = [];\n                    _u._$forEach(_keys,function(_value,_index){\n                        _arr[_index] = _map[_value]||null;\n                    });\n                    _onload(_arr);\n                });\n            }else if(_u._$isObject(_keys)){\n                _doLoadBatchData(_store,_keys,_onload);\n            }else{\n                _doLoadData(_store,_keys,_onload);\n            }\n        };\n    })();\n    /**\n     * 添加单条记录，批量添加见_$import接口\n     *\n     * 脚本举例\n     * ```javascript\n     * // 添加记录\n     * _db._$add({id:'xxxx',name:'yyyyyy',...});\n     * ```\n     *\n     * @method module:util/cache/database._$$DataBase#_$add\n     * @param    {Object|Array} arg0    - 数据对象或者列表\n     * @param    {Object}       arg1    - 其他配置信息\n     * @property {Function}     onload  - 成功回调，输入集合类型同传入参数类型一致\n     * @property {Function}     onerror - 失败回调，输入结构{code:xxx,message:'xxxx'}\n     * @return   {Void}\n     */\n    _pro._$add = function(_data,_options){\n        this._$update(_data,_options);\n    };\n    /**\n     * 更新数据，如果需要更新的数据是个HASH表，则可以使用_$import接口\n     *\n     * 脚本举例\n     * ```javascript\n     * // 更新单条记录\n     * _db._$update({id:'xxxx',name:'yyyyyy',...});\n     *\n     * // 更新一个列表的数据\n     * _db._$update([\n     *     {id:'1111',name:'xxxx',...},\n     *     {id:'2222',name:'ddddd',...},\n     *     {id:'3333',name:'ggggggg',...}\n     * ]);\n     * ```\n     *\n     * @method   module:util/cache/database._$$DataBase#_$update\n     * @param    {Array|Object} arg0    - 数据对象或者数据列表\n     * @param    {Object}       arg1    - 其他配置信息\n     * @property {Function}     onload  - 成功回调，输入集合类型同传入参数类型一致\n     * @property {Function}     onerror - 失败回调，输入结构{code:xxx,message:'xxxx'}\n     * @return   {Void}\n     */\n    _pro._$update = function(_data,_options){\n        if (!_u._$isArray(_data)){\n            _data = [_data];\n        }\n        this.__doAction('put',_data,_options);\n    };\n    /**\n     * 批量导入数据\n     *\n     * 代码举例\n     * ```javascript\n     * // 数组形式批量添加记录\n     * _db._$import([\n     *     {id:'1111',name:'yyyyyy',...},\n     *     {id:'2222',name:'yyyyyy',...},\n     *     {id:'3333',name:'yyyyyy',...}\n     * ]);\n     *\n     * // Hash表形式批量添加记录\n     * db._$import({\n     *     1111:{id:'1111',name:'yyyyyy',...},\n     *     2222:{id:'2222',name:'yyyyyy',...},\n     *     3333:{id:'3333',name:'yyyyyy',...}\n     * ]});\n     * ```\n     *\n     * @method   module:util/cache/database._$$DataBase#_$import\n     * @param    {Array|Object} arg0    - 数据集合或者数据列表\n     * @param    {Object}       arg1    - 其他配置信息\n     * @property {Function}     onload  - 成功回调，输入集合类型同传入参数类型一致\n     * @property {Function}     onerror - 失败回调，输入结构{code:xxx,message:'xxxx'}\n     * @return   {Void}\n     */\n    _pro._$import = function(_hash,_options){\n        this.__doAction('put',_hash,_options);\n    };\n    /**\n     * 删除记录\n     *\n     * 脚本举例\n     * ```javascript\n     * // 删除单条记录\n     * _db._$delete('xxxx');\n     *\n     * // 批量删除数据\n     * _db._$delete(['123','234']);\n     * ```\n     *\n     * @method   module:util/cache/database._$$DataBase#_$delete\n     * @param    {String|Number|Array} arg0    - 记录标识或者列表\n     * @param    {Object}              arg1    - 其他配置信息\n     * @property {Function}            onload  - 成功回调，输入集合类型同传入参数类型一致\n     * @property {Function}            onerror - 失败回调，输入结构{code:xxx,message:'xxxx'}\n     * @return   {Void}\n     */\n    _pro._$delete = function(_ids,_options){\n        if (!_u._$isArray(_ids)){\n            _ids = [_ids];\n        }\n        this.__doAction('delete',_ids,_options);\n    };\n    /**\n     * 清除表内容\n     *\n     * 脚本举例\n     * ```javascript\n     * // 清除表数据\n     * _db._$clear();\n     * ```\n     *\n     * @method module:util/cache/database._$$DataBase#_$clear\n     * @param    {Object}   arg0    - 其他配置信息\n     * @property {Function} onload  - 成功回调\n     * @property {Function} onerror - 失败回调，输入结构{code:xxx,message:'xxxx'}\n     * @return   {Void}\n     */\n    _pro._$clear = function(_options){\n        // remove all queue action\n        delete this.__queue;\n        // check ready\n        var _ready = this.__isDBReady(\n            this._$clear,arguments\n        );\n        if (!_ready) return;\n        // do clear\n        _options = _options||_o;\n        this.__getTransaction({\n            oncomplete:_options.onload,\n            onerror:function(_event){\n                // rollback\n                _event.preventDefault();\n                (_options.onerror||_f)(_event.target.error);\n            }\n        }).clear();\n    };\n    /**\n     * 请求数据库操作，从数据库请求数据\n     *\n     * 代码举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/cache/database'\n     * ],function(_j){\n     *     // 取数据\n     *     _j._$request({\n     *         namespace:'music.track',\n     *         action:'get',\n     *         param:[1,2,3],\n     *         onload:function(_result){\n     *             // result ->\n     *             // [{id:1,...},{id:2,...},{id:3,...}]\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/cache/database._$request\n     * @param    {Object}   arg0      - 可配置参数\n     * @property {String}   namespace - 名字空间\n     * @property {String}   action    - 操作行为，支持get/add/clear/update/import/delete\n     * @property {Variable} param     - 根据action参数确定传入的参数\n     * @property {Number}   version   - 版本信息，默认使用时间戳作为版本，必须确保在新的名字空间时给的version是递增的\n     * @property {String}   key       - 标识字段名，默认为id\n     * @property {Function} onload    - 操作完成回调\n     * @property {Function} onerror   - 操作失败回调\n     * @return   {Void}\n     */\n    _p._$request = function(_options){\n        var _opt = _u._$merge(\n            {},_options,function(_value){\n                return _u._$isFunction(_value);\n            }\n        );\n        var _handler,\n            _onload = _options.onload||_f,\n            _onerror = _options.onerror||_f,\n            _db = _p._$$DataBase._$allocate(_opt);\n        switch(_options.action){\n            case 'get'    : _handler = _db._$get;    break;\n            case 'add'    : _handler = _db._$add;    break;\n            case 'clear'  : _handler = _db._$clear;  break;\n            case 'update' : _handler = _db._$update; break;\n            case 'import' : _handler = _db._$import; break;\n            case 'delete' : _handler = _db._$delete; break;\n        }\n        if (!_handler) return;\n        _handler.call(_db,_options.param,{\n            onload:function(_result){\n                _db._$recycle();\n                _onload(_result);\n            },\n            onerror:function(_error){\n                _db._$recycle();\n                _onerror(_error);\n            }\n        });\n    };\n\n    if (CMPT){\n        NEJ.P('nej.j')._$requestByDB = _p._$request;\n        NEJ.P('nej.ut')._$$DataBase  = _p._$$DataBase;\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/cache/demo/cookie.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test cookie</title>\n    <meta charset=\"utf-8\"/>\n    <script>\n        function log(m){\n            var p = document.createElement('p');\n            p.innerHTML = m;\n            document.body.appendChild(p);\n        }\n    </script>\n  </head>\n  <body>\n    <input type=\"button\" value=\"test\" onclick=\"test();\"/>\n    <script src=\"../../../../src/define.js\"></script>\n    <script>\n      NEJ.define([\n          '../cookie.js',\n      ],function(_j){\n          \n          log('---> '+_j._$cookie('abc'));\n          \n          window.test = function(){\n              _j._$cookie('abc',{\n                  value:'aaaaaaaaaa',\n                  expires:1,\n                  path:'/'\n              });\n          };\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/cache/demo/list.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <title>test cookie</title>\n    <meta charset=\"utf-8\"/>\n    <script>\n        function log(m){\n            var p = document.createElement('p');\n            p.innerHTML = m;\n            document.body.appendChild(p);\n        }\n    </script>\n</head>\n<body>\n<script src=\"../../../define.js\"></script>\n<script>\n    NEJ.define([\n        './list.js',\n    ],function(c){\n        var inst = c._$$CustomCache._$allocate();\n        console.log(inst);\n        var list = inst._$getListInCache();\n        console.log(list);\n        inst._$clearListInCache();\n    });\n</script>\n</body>\n</html>"
  },
  {
    "path": "src/util/cache/demo/list.js",
    "content": "NEJ.define([\n\t'base/klass',\n\t'base/event',\n\t'util/event/event',\n\t'util/cache/abstract'\n],function(_k,_v,_z,_t,_p,_pro){\n\t/**\n\t *\n\t */\n\t_p._$$CustomCache = _k._$klass();\n\t_pro = _p._$$CustomCache._$extend(_t._$$CacheListAbstract);\n\t/**\n\t *\n\t * @param _options\n\t * @private\n\t */\n\t_pro.__doLoadList = function(_options){\n\n\t\t// for test\n\t\tvar _arr = [],\n\t\t\t_total = 104,\n\t\t\t_count = Math.floor(_total/_options.limit),\n\t\t\t_number = _count*_options.limit;\n\t\tvar _len = _options.offset>=_number?_total-_number:_options.limit;\n\t\tfor(var i=0;i<_total;i++){\n\t\t\t_arr.push({id:+new Date+i,name:'user-'+(+new Date+i),loginTime:+new Date});\n\t\t}\n\t\tif (_options.offset==0){\n\t\t\tthis._$setTotal(_options.key,_total);\n\t\t}\n\t\twindow.setTimeout(_options.onload._$bind(_options,_arr),1000);\n\n\t};\n\t/**\n\t * 从服务器上删除列表项，子类实现具体逻辑\n\t * @protected\n\t * @method {__doDeleteItem}\n\t * @param   {Object}   请求信息\n\t * @config  {String}   key      列表标识\n\t * @config  {Number}   id       列表项标识\n\t * @config  {String}   data     请求相关数据\n\t * @config  {Function} onload   列表项载入回调\n\t * @return {Void}\n\t */\n\t_pro.__doDeleteItem = function(_options){\n\t\t/*\n\t\t _j._$request(\n\t\t '/rest/data/delete',{\n\t\t // ...\n\t\t onload:function(_json){\n\t\t // remove from cache\n\t\t var _event = _options.onload(!0);\n\t\t // refresh list view\n\t\t _v._$dispatchEvent(\n\t\t _p._$$CustomCache,\n\t\t 'listchange',_event\n\t\t );\n\t\t }\n\t\t }\n\t\t );\n\t\t */\n\t\t// for test\n\t\twindow.setTimeout(function(){\n\t\t\tvar _event = _options.onload(!0);\n\t\t\t_v._$dispatchEvent(\n\t\t\t\t_p._$$CustomCache,\n\t\t\t\t'listchange',_event\n\t\t\t);\n\t\t},500);\n\t};\n\n\t/**\n\t * 从服务器上删除列表项，子类实现具体逻辑\n\t * @protected\n\t * @method {__doDeleteItem}\n\t * @param   {Object}   请求信息\n\t * @config  {String}   key      列表标识\n\t * @config  {Number}   id       列表项标识\n\t * @config  {String}   data     请求相关数据\n\t * @config  {Function} onload   列表项载入回调\n\t * @return {Void}\n\t */\n\t_pro.__doUpdateItem = function(_options){\n\n\t\t// for test\n\t\twindow.setTimeout(function(){\n\t\t\t_options.data.name = 'up-'+(+new Date);\n\t\t\tvar _event = _options.onload(_options.data);\n\t\t\t_v._$dispatchEvent(\n\t\t\t    _p._$$CustomCache,\n\t\t\t\t'listchange',_event\n\t\t\t);\n\t\t},500);\n\n\t};\n\n\t_z._$$CustomEvent._$allocate({\n\t\telement:_p._$$CustomCache,\n\t\tevent:'listchange'\n\t});\n\n\treturn _p;\n});\n"
  },
  {
    "path": "src/util/cache/demo/storage.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test cookie</title>\n    <meta charset=\"utf-8\"/>\n    <script>\n        function log(m){\n            var p = document.createElement('p');\n            p.innerHTML = m;\n            document.body.appendChild(p);\n        }\n    </script>\n  </head>\n  <body>\n    <input type=\"button\" value=\"set\" onclick=\"test();\"/>\n    <input type=\"button\" value=\"get\" onclick=\"test2();\"/>\n    <script src=\"../../../define.js\"></script>\n    <script>\n      NEJ.define([\n          '../storage.js'\n      ],function(_j){\n          window.test2 = function(){\n              log('---> '+_j._$getDataInStorage('abc'));\n          }\n\n          window.test = function(){\n              _j._$setDataInStorage('abc',{\n                  value:'aaaaaaaaaa',\n                  expires:1,\n                  path:'/'\n              });\n          };\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/cache/list.js",
    "content": "/*\n * ------------------------------------------\n * 列表缓存管理器实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/cache/list */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    './cache.js'\n],function(NEJ,_k,_u,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 列表缓存管理器\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/ajax/xdr',\n     *     'util/cache/list'\n     * ],function(_j,_t){\n     *     var _cache = _t._$$CacheList._$allocate({\n     *         id:'abc',\n     *         doloadlist:function(_options){\n     *             // 从服务器加载列表\n     *             _j._$request(\n     *                 '/api/list',{\n     *                     data:_options.data,\n     *                     onload:function(_list){\n     *                         _options.onload(_list);\n     *                     }\n     *                 }\n     *             );\n     *         },\n     *         doloaditem:function(_options){\n     *             // 从服务器加载数据项\n     *             _j._$request(\n     *                 '/api/get',{\n     *                     data:_options.data,\n     *                     onload:function(_item){\n     *                         _options.onload(_item);\n     *                     }\n     *                 }\n     *             );\n     *         },\n     *         doadditem:function(_options){\n     *             // 往服务器添加数据项\n     *             _j._$request(\n     *                 '/api/add',{\n     *                     data:_options.data,\n     *                     onload:function(_item){\n     *                         _options.onload(_item);\n     *                     }\n     *                 }\n     *             );\n     *         },\n     *         dodeleteitem:function(_options){\n     *             // 从服务器删除数据项\n     *             _j._$request(\n     *                 '/api/delete',{\n     *                     data:_options.data,\n     *                     onload:function(_item){\n     *                         _options.onload(_item);\n     *                     }\n     *                 }\n     *             );\n     *         },\n     *         doupdateitem:function(_options){\n     *             // 更新数据项至服务器\n     *             _j._$request(\n     *                 '/api/update',{\n     *                     data:_options.data,\n     *                     onload:function(_item){\n     *                         _options.onload(_item);\n     *                     }\n     *                 }\n     *             );\n     *         },\n     *         dopullrefresh:function(_options){\n     *             // 从服务器加载列表\n     *             _j._$request(\n     *                 '/api/pull',{\n     *                     data:_options.data,\n     *                     onload:function(_list){\n     *                         _options.onload(_list);\n     *                     }\n     *                 }\n     *             );\n     *         }\n     *     });\n     *\n     *     // 第一个列表的请求\n     *     _cache._$getList({key:'abc',data:{},offset:0,limit:10})\n     *     // 不会发请求，直接走缓存\n     *     _cache._$getList({key:'abc',data:{},offset:0,limit:10})\n     *     // 第一个项请求\n     *     _cache._$getItem({id:'abc',key:'123',data:{})\n     *     // 不会发请求，直接走缓存\n     *     _cache._$getItem({id:'abc',key:'123',data:{})\n     * });\n     * ```\n     *\n     * @class   module:util/cache/list._$$CacheList\n     * @extends module:util/cache/cache._$$CacheAbstract\n     *\n     * @param    {Object}  config  - 可选配置参数\n     * @property {String}  id      - 缓存标识，默认使用构造器缓存\n     * @property {String}  key     - 列表项标识字段，默认为id\n     * @property {Object}  data    - 列表关联数据\n     * @property {Boolean} autogc  - 是否自动操作\n     */\n    /**\n     * 列表载入完成回调\n     * \n     * @event    module:util/cache/list._$$CacheList#onlistload\n     * @param    {Object}   event - 可选配置参数\n     * @property {String}   key   - 列表标识\n     * @property {Variable} ext   - 传入数据原样返回\n     */\n    /**\n     * 缓存项载入完成回调\n     * \n     * @event    module:util/cache/list._$$CacheList#onitemload\n     * @param    {Object}   event - 可选配置参数\n     * @property {String}   id    - 项标识\n     * @property {String}   key   - 列表标识\n     * @property {Variable} ext   - 传入数据原样返回\n     */\n    /**\n     * 缓存项添加完成回调\n     * \n     * @event    module:util/cache/list._$$CacheList#onitemadd\n     * @param    {Object}   event - 可选配置参数\n     * @property {String}   key   - 列表标识\n     * @property {Object}   data  - 添加的数据对象\n     * @property {Variable} ext   - 传入数据原样返回\n     */\n    /**\n     * 缓存项删除完成回调\n     * \n     * @event    module:util/cache/list._$$CacheList#onitemdelete\n     * @param    {Object}   event - 可选配置参数\n     * @property {String}   key   - 列表标识\n     * @property {Object}   data  - 删除的数据对象\n     * @property {Variable} ext   - 传入数据原样返回\n     */\n    /**\n     * 缓存项更新完成回调\n     * \n     * @event    module:util/cache/list._$$CacheList#onitemupdate\n     * @param    {Object}   event - 可选配置参数\n     * @property {String}   key   - 列表标识\n     * @property {Object}   data  - 更新的数据对象\n     * @property {Variable} ext   - 传入数据原样返回\n     */\n    /**\n     * 服务器最新列表拉取完成回调\n     * \n     * @event    module:util/cache/list._$$CacheList#onpullrefresh\n     * @param    {Object}   event - 可选配置参数\n     * @property {String}   key   - 列表标识\n     * @property {Variable} ext   - 传入数据原样返回\n     */\n    /**\n     * 从服务器载入列表\n     * \n     * @event    module:util/cache/list._$$CacheList#doloadlist\n     * @param    {Object}   event  - 可选配置参数\n     * @property {String}   key    - 列表标识\n     * @property {Variable} ext    - 回调回传数据\n     * @property {Number}   data   - 需要提交到服务器的其他信息\n     * @property {Number}   offset - 偏移量\n     * @property {Number}   limit  - 数量\n     * @property {Function} onload - 请求回调\n     */\n    /**\n     * 从服务器载入数据项\n     * \n     * @event    module:util/cache/list._$$CacheList#doloaditem\n     * @param    {Object}   event  - 可选配置参数\n     * @property {String}   id     - 项标识\n     * @property {String}   key    - 列表标识\n     * @property {Variable} ext    - 回调回传数据\n     * @property {Number}   data   - 需要提交到服务器的其他信息\n     * @property {Function} onload - 请求回调\n     */\n    /**\n     * 往服务器添加数据项\n     * \n     * @event    module:util/cache/list._$$CacheList#doadditem\n     * @param    {Object}   event  - 可选配置参数\n     * @property {String}   key    - 列表标识\n     * @property {Variable} ext    - 回调回传数据\n     * @property {String}   data   - 数据项对象\n     * @property {Function} onload - 请求回调\n     */\n    /**\n     * 从服务器删除数据项\n     * \n     * @event    module:util/cache/list._$$CacheList#dodeleteitem\n     * @param    {Object}   event  - 可选配置参数\n     * @property {String}   key    - 列表标识\n     * @property {Variable} ext    - 回调回传数据\n     * @property {String}   data   - 数据项对象\n     * @property {Function} onload - 请求回调\n     */\n    /**\n     * 更新服务器数据项\n     * \n     * @event    module:util/cache/list._$$CacheList#doupdateitem\n     * @param    {Object}   event  - 可选配置参数\n     * @property {String}   key    - 列表标识\n     * @property {Variable} ext    - 回调回传数据\n     * @property {String}   data   - 数据项对象\n     * @property {Function} onload - 请求回调\n     */\n    /**\n     * 从服务器拉取最新列表\n     * \n     * @event    module:util/cache/list._$$CacheList#dopullrefresh\n     * @param    {Object}   event  - 可选配置参数\n     * @property {String}   key    - 列表标识\n     * @property {Variable} ext    - 回调回传数据\n     * @property {Function} onload - 请求回调\n     */\n    _p._$$CacheList = _k._$klass();\n    _pro = _p._$$CacheList._$extend(_t._$$CacheAbstract);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__key = _options.key||'id';\n        this.__data = _options.data||_o;\n        this.__auto = !!_options.autogc;\n        this.__doSwapCache(_options.id);\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__destroy\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        // check gc schedule\n        if (!!this.__timer){\n            this.__doGCAction();\n        }\n    };\n    /**\n     * 切换缓存\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__doSwapCache\n     * @param  {String} arg0 - 缓存标识\n     * @return {Void}\n     */\n    _pro.__doSwapCache = function(_id){\n        var _cache;\n        if (!!_id){\n            _cache = this.__cache[_id];\n            if (!_cache){\n                _cache = {};\n                this.__cache[_id] = _cache;\n            }\n        }\n        _cache = _cache||this.__cache;\n        _cache.hash = _cache.hash||{};\n        // hash    [Object] - item map by id\n        // list    [Array]  - default list\n        // x-list  [Array]  - list with key 'x'\n        this.__lspl = _cache;\n    };\n    /**\n     * 执行GC行为\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__doGCAction\n     * @return {Void}\n     */\n    _pro.__doGCAction = function(){\n        this.__timer = window.clearTimeout(this.__timer);\n        // dump id map for used items\n        var _map = {};\n        _u._$loop(\n            this.__lspl,function(_list,_key){\n                if (_key=='hash') return;\n                if (!_u._$isArray(_list)) return;\n                _u._$forEach(_list,function(_item){\n                    if (!_item) return;\n                    _map[_item[this.__key]] = !0;\n                },this);\n            },this\n        );\n        // check used in hash\n        _u._$loop(\n            this.__getHash(),\n            function(_item,_id,_hash){\n                if (!_map[_id]){\n                    delete _hash[_id];\n                }\n            }\n        );\n    };\n    /**\n     * 调度执行GC操作，删除不用的数据对象\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__doGCSchedule\n     * @return {Void}\n     */\n    _pro.__doGCSchedule = function(){\n        if (!!this.__timer){\n            this.__timer = window.clearTimeout(this.__timer);\n        }\n        this.__timer = window.setTimeout(\n            this.__doGCAction._$bind(this),150\n        );\n    };\n    /**\n     * 缓存列表项\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__doSaveItemToCache\n     * @param  {Object|Array} arg0 - 列表项或列表\n     * @param  {String}       arg1 - 列表标识\n     * @return {Object|Array}        缓存中列表项或列表\n     */\n    _pro.__doSaveItemToCache = function(_item,_lkey){\n        // save item to cache\n        if (!_u._$isArray(_item)){\n            _item = this.__doFormatItem(_item,_lkey)||_item;\n            if (!_item) return null;\n            var _key = _item[this.__key];\n            if (_key!=null){\n                var _itm = this.__getHash()[_key];\n                if (!!_itm){\n                    _item = _u._$merge(_itm,_item);\n                }\n                this.__getHash()[_key] = _item;\n            }\n            delete _item.__dirty__;\n            return _item;\n        }\n        // batch save to cache\n        var _result = [];\n        _u._$forEach(\n            _item,function(_it){\n                _result.push(\n                    this.__doSaveItemToCache(_it,_lkey)\n                );\n            },this\n        );\n        return _result;\n    };\n    /**\n     * 从缓存列表删除项\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__doRemoveItemFromList\n     * @param  {String}       arg0 - 列表标识\n     * @param  {String|Array} arg1 - 项标识,['111',{id:'222',...},...]\n     * @return {Object|Array}        删除项\n     */\n    _pro.__doRemoveItemFromList = function(_lkey,_id){\n        var _result = null,\n            _pkey = this.__key;\n        // remove one item\n        if (!_u._$isArray(_id)){\n            var _result = null,\n                _pkey = this.__key;\n            _id = _id[_pkey]||_id;\n            var _list = this._$getListInCache(_lkey),\n                _index = _u._$indexOf(_list,function(_itm){\n                    return !!_itm&&_itm[_pkey]==_id;\n                });\n            if (_index>=0){\n                _result = _list[_index];\n                _list.splice(_index,1);\n            }\n            return _result;\n        }\n        // batch remove items\n        var _result = [];\n        _u._$reverseEach(\n            _id,function(_item){\n                _result.unshift(\n                    this.__doRemoveItemFromList(_lkey,_item)\n                );\n            },this\n        );\n        return _result;\n    };\n    /**\n     * 格式化数据项，子类实现具体业务逻辑\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__doFormatItem\n     * @param  {Object} arg0 - 列表项\n     * @param  {String} arg1 - 列表标识\n     * @return {Object}        格式化后的列表项\n     */\n    _pro.__doFormatItem = _f;\n    /**\n     * 前向追加列表项至列表\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__doUnshiftToList\n     * @param  {String}       arg0 - 列表标识\n     * @param  {Object|Array} arg1 - 列表项或者列表\n     * @return {Void}\n     */\n    _pro.__doUnshiftToList = function(_key,_item){\n        if (!_item) return;\n        // item unshift\n        if (!_u._$isArray(_item)){\n            var _list = this._$getListInCache(_key),\n                _item = this.__doSaveItemToCache(_item,_key);\n            if (!!_item) _list.unshift(_item);\n            return;\n        }\n        // batch unshift\n        _u._$reverseEach(\n            _item,function(_it){\n                this.__doUnshiftToList(_key,_it);\n            },this\n        );\n    };\n    /**\n     * 设置列表总数\n     *\n     * 脚本举例\n     * ```javascript\n     * // 列表总数已知的情况，这时候的total是100\n     * // 因为这个100是第一次请求，从服务器带过来的缓存的，后续可能会变化\n     * // 但是当前页面的总页面无法做出这种适应，所以不用有相应的变化\n     * // 注意：cache是无法保证数据的同步的。如果在别的地方有数据删除，cache无法获知，需要刷新页面\n     * _cc._$setTotal('abc',100);\n     *\n     * // 列表总数未知的情况，这时候的total是list的长度\n     * // 未知总长度会有更多选项出现\n     * var _total = _cc._$getTotal('abc');\n     * // 如果offset+limit>_total说明已经没有数据了，把更多隐藏掉\n     * // 否则会继续有一个更多选项在末尾\n     * ```\n     *\n     * @method module:util/cache/list._$$CacheList#_$setTotal\n     * @see    module:util/cache/list._$$CacheList#_$getTotal\n     * @param  {String} arg0 - 列表缓存键值\n     * @param  {Number} arg1 - 列表总数\n     * @return {Void}\n     */\n    _pro._$setTotal = function(_key,_total){\n        var _list = this._$getListInCache(_key);\n        _list.length = Math.max(_list.length,_total);\n        this._$setLoaded(_key);\n    };\n    /**\n     * 取列表总长度\n     *\n     * 脚本举例\n     * ```javascript\n     * // 获取列表总长度，未知页码的情况是total和list.length较长的一个\n     * // 页面已知的情况，取total的值\n     * // 以上值被设置到list的length属性中\n     * _cc._$getTotal('abc');\n     * ```\n     *\n     * @method module:util/cache/list._$$CacheList#_$getTotal\n     * @see    module:util/cache/list._$$CacheList#_$setTotal\n     * @param  {String} arg0 - 列表标识\n     * @return {Number}        列表总长度\n     */\n    _pro._$getTotal = function(_key){\n        return this._$getListInCache(_key).length;\n    };\n    /**\n     * 设置未知长度列表的载入完成标志\n     *\n     * 脚本举例\n     * ```javascript\n     * // 设置key为abc的完整数据已经载入完成\n     * _cc._$setLoaded('abc');\n     * ```\n     *\n     * @method module:util/cache/list._$$CacheList#_$setLoaded\n     * @param  {String} arg0 - 列表标识\n     * @return {Void}\n     */\n    _pro._$setLoaded = function(_key,_loaded){\n        this._$getListInCache(_key).loaded = _loaded!==!1;\n    };\n    /**\n     * 判断列表是否载入完成\n     *\n     * @method module:util/cache/list._$$CacheList#_$isLoaded\n     * @param  {String}  arg0 - 列表标识\n     * @return {Boolean}        是否载入完成\n     */\n    _pro._$isLoaded = function(_key){\n        return !!this._$getListInCache(_key).loaded;\n    };\n    /**\n     * 设置列表，清除原有列表\n     *\n     * 脚本举例\n     * ```javascript\n     * // 设置列表\n     * _cc._$setListInCache('abc',[]);\n     * ```\n     *\n     * @method module:util/cache/list._$$CacheList#_$setListInCache\n     * @param  {String} arg0 - 列表标识\n     * @return {Array}         列表\n     */\n    _pro._$setListInCache = function(_key,_list){\n        this._$clearListInCache(_key);\n        this.__getList({\n            key:_key,\n            offset:0,\n            limit:_list.length+1\n        },{\n            list:_list,\n            total:_list.length\n        });\n    };\n    /**\n     * 直接从缓存中取列表\n     *\n     * 脚本举例\n     * ```javascript\n     * // 从cache里取列表数据\n     * _cc._$getListInCache('abc');\n     * ```\n     *\n     * @method module:util/cache/list._$$CacheList#_$getListInCache\n     * @param  {String} arg0 - 列表标识\n     * @return {Array}         列表\n     */\n    _pro._$getListInCache = (function(){\n        var _doFormatKey = function(_key){\n            return (_key||'')+(!_key?'':'-')+'list';\n        };\n        return function(_key){\n            var _key = _doFormatKey(_key),\n                _list = this.__lspl[_key];\n            if (!_list){\n                _list = [];\n                this.__lspl[_key] = _list;\n            }\n            return _list;\n        };\n    })();\n    /**\n     * 取Hash映射表\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__getHash\n     * @return {Object} 映射表\n     */\n    _pro.__getHash = function(){\n        var _hash = this.__lspl.hash;\n        if (!_hash){\n            _hash = {};\n            this.__lspl.hash = _hash;\n        }\n        return _hash;\n    };\n    /**\n     * 前向刷新列表\n     * \n     * @method   module:util/cache/list._$$CacheList#_$pullRefresh\n     * @param    {Object} arg0 - 可选配置参数\n     * @property {String} key  - 列表标识\n     * @property {Number} data - 发送到服务器数据信息\n     * @return   {Void}\n     */\n    _pro._$pullRefresh = (function(){\n        var _doFormatKey = function(_options){\n            return 'r-'+_options.key;\n        };\n        return function(_options){\n            var _ropt = _u._$merge({},_options),\n                _rkey = _doFormatKey(_ropt),\n                _callback = this._$dispatchEvent._$bind(this);\n            if (!this.__doQueueRequest(_rkey,_callback)){\n                _ropt.rkey = _rkey;\n                _ropt.onload = this.__pullRefresh._$bind(this,_ropt);\n                this._$dispatchEvent('dopullrefresh',_ropt);\n            }\n        };\n    })();\n    /**\n     * 前向取列表回调\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__pullRefresh\n     * @param  {Object} arg0 - 请求信息\n     * @param  {Array}  arg1 - 数据列表\n     * @return {Void}\n     */\n    _pro.__pullRefresh = function(_options,_result){\n        // list with total\n        // {total:12,result:[]} 或者 {total:13,list:[]}\n        var _key = _options.key,\n            _total = parseInt(_result.total),\n            _list = _result.list||_result.result;\n        this.__doUnshiftToList(_key,_list||_result);\n        if (!isNaN(_total)&&!!_list){\n            this._$getListInCache(_key).length = _total;\n            this._$setLoaded(_key);\n        }\n        this.__doCallbackRequest(\n            _options.rkey,'onpullrefresh',_options\n        );\n    };\n    /**\n     * 取列表请求标识\n     *\n     * @private\n     * @method   module:util/cache/list._$$CacheList#__getListReqKey\n     * @param    {Object} options - 请求配置信息\n     * @returns  {String} 请求标识\n     */\n    _pro.__getListReqKey = function (options) {\n        return 'r-'+options.key+'-'+\n            options.offset+'-'+options.limit;\n    };\n    /**\n     * 取列表\n     *\n     * 脚本举例\n     * ```javascript\n     * _cc._$getList({key:'abc',data:{},offset:0,limit:10});\n     * ```\n     *\n     * @method   module:util/cache/list._$$CacheList#_$getList\n     * @param    {Object} arg0   - 可选配置参数\n     * @property {String} key    - 列表标识\n     * @property {Number} data   - 其他数据信息\n     * @property {Number} offset - 偏移量\n     * @property {Number} limit  - 数量\n     * @property {Object} ext    - 回传数据\n     * @return   {Void}\n     */\n    _pro._$getList = function(_options){\n        _options = _options||_o;\n        var _ropt = {\n                key:(''+_options.key)||'',\n                ext:_options.ext||null,\n                data:_options.data||null,\n                offset:parseInt(_options.offset)||0,\n                limit:parseInt(_options.limit)||0\n            },\n            _list = this._$getListInCache(_ropt.key),\n            _has = this.__hasFragment(\n                _list,_ropt.offset,_ropt.limit\n            );\n        // hit in memory\n        if (_has){\n            this._$dispatchEvent('onlistload',_ropt);\n            return;\n        }\n        // load from server\n        var _that = this,\n            _rkey = this.__getListReqKey(_ropt),\n            _callback = function (name, opt) {\n                _that._$dispatchEvent(name, _ropt);\n            };\n        if (!this.__doQueueRequest(_rkey,_callback)){\n            _ropt.rkey = _rkey;\n            _ropt.onload = this.__getList._$bind(this,_ropt);\n            this._$dispatchEvent('doloadlist',_ropt);\n        }\n    };\n    /**\n     * 取列表回调\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__getList\n     * @param  {Object}       arg0 - 请求信息\n     * @param  {Array|Object} arg1 - 数据列表，或者带总数信息列表\n     * @return {Void}\n     */\n    _pro.__getList = (function(){\n        var _doClear = function(_item,_index,_list){\n            if (!!_item){\n                return !0;\n            }\n            _list.splice(_index,1);\n        };\n        return function(_options,_result){\n            _options = _options||_o;\n            // clear lock if no result\n            if (!_result){\n                // do callback\n                this.__doCallbackRequest(\n                    _options.rkey,'onlistload',_options\n                );\n                return;\n            }\n            // save list to cache\n            var _key = _options.key,\n                _offset = _options.offset,\n                _chlist = this._$getListInCache(_key);\n            // list with total\n            // {total:12,result:[]} 或者 {total:13,list:[]}\n            var _list = _result||[];\n            if (!_u._$isArray(_list)){\n                _list = _result.result||_result.list||[];\n                var _total = parseInt(_result.total);\n                if (!isNaN(_total)||_total>_list.length){\n                    this._$setTotal(_key,_total);\n                }\n            }\n            // merge list\n            _u._$forEach(\n                _list,function(_item,_index){\n                    _chlist[_offset+_index] = this.\n                         __doSaveItemToCache(_item,_key);\n                },this\n            );\n            // check list all loaded\n            if (_list.length<_options.limit){\n                this._$setLoaded(_key);\n                _u._$reverseEach(_chlist,_doClear);\n            }\n            // do callback\n            this.__doCallbackRequest(\n                _options.rkey,'onlistload',_options\n            );\n        };\n    })();\n    /**\n     * 清除缓存列表\n     *\n     * 脚本举例\n     * ```javascript\n     * // 取列表数据\n     * _cc._$clearListInCache('abc');\n     * ```\n     *\n     * @method module:util/cache/list._$$CacheList#_$clearListInCache\n     * @param  {String} arg0 - 列表标识\n     * @return {Void}\n     */\n    _pro._$clearListInCache = (function(){\n        var _doClear = function(_item,_index,_list){\n            _list.splice(_index,1);\n        };\n        return function(_key){\n            if (_u._$isString(_key)){\n                // clear one list\n                var _list = this._$getListInCache(_key);\n                // fix GC bug\n                _list.splice(0, _list.length);\n                // _u._$reverseEach(_list,_doClear);\n                this._$setLoaded(_key,!1);\n                if (this.__auto){\n                    this.__doGCSchedule();\n                }\n            }else{\n                // clear all list\n                _u._$loop(\n                    this.__lspl,function(_list,_key){\n                        if (_key=='hash'||\n                           !_u._$isArray(_list)) return;\n                        _key = _key.substr(0,_key.length-5);\n                        this._$clearListInCache(_key);\n                    },this\n                );\n            }\n        };\n    })();\n    /**\n     * 验证项缓存中的项是否有效，子类可重写\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__doCheckItemValidity\n     * @param  {Object}  arg0 - 数据项\n     * @param  {String}  arg0 - 列表标识\n     * @return {Boolean}        是否有效\n     */\n    _pro.__doCheckItemValidity = function(_item,_lkey){\n        return !_item.__dirty__;\n    };\n    /**\n     * 从缓存中取列表项\n     *\n     * 脚本举例\n     * ```javascript\n     * // 从cache中取某一项数据\n     * _cc._$getItemInCache('abc');\n     * ```\n     *\n     * @method module:util/cache/list._$$CacheList#_$getItemInCache\n     * @param  {String}   arg0 - 项标识\n     * @return {Variable}        列表项\n     */\n    _pro._$getItemInCache = function(_id){\n        return this.__getHash()[_id];\n    };\n    /**\n     * 清除缓存项\n     * \n     * @method module:util/cache/list._$$CacheList#_$clearItemInCache\n     * @param  {String} arg0 - 项标识\n     * @return {Void}\n     */\n    _pro._$clearItemInCache = function(_id){\n        var _item = this._$getItemInCache(_id);\n        if (!!_item) _item.__dirty__ = !0;\n    };\n    /**\n     * 获取加载单项的请求标识\n     *\n     * @private\n     * @method  module:util/cache/list._$$CacheList#__getItemReqKey\n     * @param   {Object} options - 请求配置\n     * @returns {String} 请求标识\n     */\n    _pro.__getItemReqKey = function (options) {\n        return 'r-'+options.key+'-'+options.id;\n    };\n    /**\n     * 取列表项项\n     *\n     * 脚本举例\n     * ```javascript\n     * // 取某一项数据\n     * _cc._$getItem({\n     *     id:'aaaa',\n     *     key:'xxxxxx'\n     * });\n     * ```\n     *\n     * @method   module:util/cache/list._$$CacheList#_$getItem\n     * @param    {Object} event - 请求信息\n     * @property {String} id    - 项标识，该名称与配置的项标识键一致\n     * @property {String} key   - 列表标识\n     * @property {Object} data  - 发送到服务器的数据\n     * @property {Object} ext   - 需要回传的数据信息\n     * @return   {Void}\n     */\n    _pro._$getItem = function(_options){\n        _options = _options||_o;\n        var _id = _options[this.__key]||_options.id,\n            _ropt = {\n                id:_id,\n                ext:_options.ext,\n                data:_options.data||{},\n                key:(''+_options.key)||''\n            };\n        var _item = this._$getItemInCache(_id);\n        _ropt.data[this.__key] = _id;\n        // hit in memory\n        if (!!_item&&\n            this.__doCheckItemValidity(_item,_ropt.key)){\n            this._$dispatchEvent('onitemload',_ropt);\n            return;\n        }\n        // load from server\n        var _that = this,\n            _rkey = this.__getItemReqKey(_ropt),\n            _callback = function (name, opt) {\n                _that._$dispatchEvent(name, _ropt);\n            };\n        if (!this.__doQueueRequest(_rkey,_callback)){\n            _ropt.rkey = _rkey;\n            _ropt.onload = this.__getItem._$bind(this,_ropt);\n            this._$dispatchEvent('doloaditem',_ropt);\n        }\n    };\n    /**\n     * 取列表项回调\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__getItem\n     * @param  {Object} arg0 - 请求信息\n     * @param  {Object} arg1 - 列表项对象\n     * @return {Void}\n     */\n    _pro.__getItem = function(_options,_item){\n        _options = _options||_o;\n        this.__doSaveItemToCache(_item,_options.key);\n        this.__doCallbackRequest(\n            _options.rkey,'onitemload',_options\n        );\n    };\n    /**\n     * 添加列表项\n     *\n     * 脚本举例\n     * ```javascript\n     * _cc._$addItem({\n     *     key: '123',\n     *     item: {},\n     *     push: false,\n     *     offset:0\n     * });\n     * ```\n     *\n     * @method   module:util/cache/list._$$CacheList#_$addItem\n     * @param    {Object}  arg0   - 配置信息\n     * @property {String}  key    - 列表标识\n     * @property {Object}  data   - 列表项数据\n     * @property {Boolean} push   - 是否追加到列表尾部\n     * @property {Number}  offset - 对于非尾部追加的项可通过此参数指定追加位置\n     * @return   {Void}\n     */\n    _pro._$addItem = function(_options){\n        _options = _u._$merge({},_options);\n        _options.onload = this.__addItem._$bind(this,_options);\n        this._$dispatchEvent('doadditem',_options);\n    };\n    /**\n     * 添加列表项回调\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__addItem}\n     * @param  {Object} arg0 - 请求信息\n     * @param  {Object} arg1 - 列表项对象\n     * @return {Void}\n     */\n    _pro.__addItem = function(_options,_item){\n        var _key = _options.key,\n            _flag = 0;\n        // add one item to cache\n        var addOneItem = function(item){\n            var _item = this.__doSaveItemToCache(item,_key);\n            // add to list\n            if (!!_item){\n                var _list = this._$getListInCache(_key);\n                if (!_options.push){\n                    _flag = -1;\n                    var _offset = _options.offset||0;\n                    _list.splice(_offset,0,_item);\n                }else if(_list.loaded){\n                    _flag = 1;\n                    _list.push(_item);\n                }else{\n                    // add total\n                    _list.length++;\n                }\n            }\n            return _item;\n        };\n\n        // check batch add\n        if (_u._$isArray(_item)){\n            var ret = [];\n            _u._$forEach(_item,function(it){\n                ret.push(addOneItem.call(this,it));\n            },this);\n            _item = ret;\n        }else{\n            _item = addOneItem.call(this,_item);\n        }\n\n        // callback\n        var _event = {\n            key:_key,\n            flag:_flag,\n            data:_item,\n            action:'add',\n            ext:_options.ext\n        };\n        this._$dispatchEvent('onitemadd',_event);\n\n        return _event;\n    };\n    /**\n     * 删除列表项\n     *\n     * 脚本举例\n     * ```javascript\n     * _cc._$deleteItem({\n     *     key: '123'\n     * });\n     * ```\n     *\n     * @method   module:util/cache/list._$$CacheList#_$deleteItem\n     * @param    {Object} arg0 - 配置信息\n     * @property {String} key  - 列表标识\n     * @property {String} id   - 列表项标识\n     * @property {Object} data - 列表项数据信息\n     * @property {Object} ext  - 需要回传的数据信息\n     * @return   {Void}\n     */\n    _pro._$deleteItem = function(_options){\n        _options = _u._$merge({},_options);\n        _options.onload = this.__deleteItem._$bind(this,_options);\n        this._$dispatchEvent('dodeleteitem',_options);\n    };\n    /**\n     * 删除列表项回调\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__deleteItem\n     * @param  {Object}  arg0 - 请求信息\n     * @param  {Boolean} arg1 - 是否删除成功\n     * @return {Void}\n     */\n    _pro.__deleteItem = function(_options,_isok){\n        var _item,\n            _key = _options.key;\n        // sync memory\n        if (!!_isok){\n            var _id = _options.id;\n            _item = this._$getItemInCache(_id)||null;\n            this.__doRemoveItemFromList(_key,_id);\n        }\n        // callback\n        var _event = {\n            key:_key,\n            data:_item,\n            result:_isok,\n            action:'delete',\n            ext:_options.ext\n        };\n        this._$dispatchEvent('onitemdelete',_event);\n\n        return _event;\n    };\n    /**\n     * 更新列表项\n     *\n     * 脚本举例\n     * ```javascript\n     * _cc._$updateItem({\n     *     key:'123',\n     *     item:{}\n     * });\n     * ```\n     *\n     * @method   module:util/cache/list._$$CacheList#_$updateItem\n     * @param    {Object} arg0 - 配置信息\n     * @property {String} key  - 列表标识\n     * @property {Object} data - 列表项数据\n     * @property {Object} ext  - 需要回传的数据信息\n     * @return   {Void}\n     */\n    _pro._$updateItem = function(_options){\n        _options = _u._$merge({},_options);\n        _options.onload = this.__updateItem._$bind(this,_options);\n        this._$dispatchEvent('doupdateitem',_options);\n    };\n    /**\n     * 更新列表项回调\n     * \n     * @protected\n     * @method module:util/cache/list._$$CacheList#__updateItem\n     * @param  {Object} arg0 - 请求信息\n     * @param  {Object} arg1 - 列表项对象\n     * @return {Void}\n     */\n    _pro.__updateItem = function(_options,_item){\n        var _key = _options.key;\n        // update memory\n        if (!!_item){\n            _item = this.__doSaveItemToCache(_item,_key);\n        }\n        // callback\n        var _event = {\n            key:_key,\n            data:_item,\n            result:_item,\n            action:'update',\n            ext:_options.ext\n        };\n        this._$dispatchEvent('onitemupdate',_event);\n\n        return _event;\n    };\n\n    if (CMPT){\n        NEJ.P('nej.ut')._$$ListCache = _p._$$CacheList;\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/cache/manager.js",
    "content": "/*\n * ------------------------------------------\n * 持久化数据管理器实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/cache/manager */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    'util/cache/cache'\n],function(NEJ,_k,_u,_t0,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 分块持久化数据管理器\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/cache/manager'\n     * ],function(_t){\n     *     // 实例化管理器\n     *     var inst = _t._$$StorageManager._$allocate({\n     *         key:'userId',\n     *         prefix:'test-user-',\n     *         limit:2\n     *     });\n     *    \n     *     // memory中存储结构类似：\n     *     // {\n     *     //    // 数据引用数及对应的块标识\n     *     //    'test-user-index':{\n     *     //         '1':{ref:1,block:0},\n     *     //         '2':{ref:1,block:0},\n     *     //         '3':{ref:1,block:1}\n     *     //     },\n     *     //     // 每块包含的数据ID列表\n     *     //     'test-user-block':[\n     *     //         [1,2],\n     *     //         [3]\n     *     //     ],\n     *     //     // 所有数据的映射表\n     *     //     'test-user-data':{\n     *     //         '1':{userId:1,name:'11111'},\n     *     //         '2':{userId:2,name:'22222'},\n     *     //         '3':{userId:3,name:'33333'}\n     *     //     },\n     *     //     // 每个块的初始数据长度\n     *     //     'test-user-blen':[\n     *     //         2,1\n     *     //     ]\n     *     // }\n     *    \n     *     // storage中存储结构类似：\n     *     // test-user-index:{'1':{b:'0',r:1},'2':{b:'0',r:2},'3':{b:'1',r:1},'test-user-blen':[2,1]}\n     *     // test-user-0:[{userId:1,name:'11111'},{userId:2,name:'22222'}]\n     *     // test-user-1:[{userId:3,name:'33333'}]\n     *    \n     *     // 添加数据\n     *     inst._$add({userId:1,name:'11111'});\n     *     inst._$add({userId:2,name:'22222'});\n     *     inst._$add({userId:3,name:'33333'});\n     *     // 重复添加更新引用计数\n     *     inst._$add({userId:1,name:'11111'});\n     *     // 删除数据，优先删除引用计数，当引用计数为0时删除storage中数据\n     *     inst._$delete(1);\n     *     // 更新数据\n     *     inst._$update({userId:1,name:'aaaaaa'});\n     *     // 取数据对象\n     *     var user = inst._$get(1);\n     * });\n     * ```\n     *\n     * @class    module:util/cache/manager._$$StorageManager\n     * @extends  module:util/cache/cache._$$CacheAbstract\n     *\n     * @param    {Object} config - 配置参数\n     * @property {String} key    - 数据标识键名称，默认为id\n     * @property {String} prefix - 存储键前缀，也用于标识数据块，相同前缀的数据为同一份\n     * @property {Number} limit  - 单块数据长度限制，默认单块数组长度为500\n     */\n    _p._$$StorageManager = _k._$klass();\n    _pro = _p._$$StorageManager._$extend(_t0._$$CacheAbstract);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/cache/manager._$$StorageManager#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = (function(){\n        var _lock = {};\n        return function(_options){\n            this.__super(_options);\n            this.__pkey = _options.key||'id';\n            this.__prefix = ''+(_options.prefix||'');\n            this.__limit = parseInt(_options.limit)||500;\n            // init data\n            if (!_lock[this.__prefix]){\n                _lock[this.__prefix] = !0;\n                this.__doInitDataFromStorage();\n            }\n        };\n    })();\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/cache/manager._$$StorageManager#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__pkey;\n        delete this.__limit;\n        delete this.__prefix;\n    };\n    /**\n     * 构建存储结构\n     * \n     * @protected\n     * @method module:util/cache/manager._$$StorageManager#__doInitDataFromStorage\n     * @return {Void}\n     */\n    _pro.__doInitDataFromStorage = function(){\n        var _ext,\n            _prefix = this.__prefix,\n            _midx = this.__getIndex();\n        // init form storage data\n        _u._$forIn(\n            this.__getDataInStorage(_prefix+'index'),\n            function(_conf,_id){\n                if (_id==_prefix+'blen'){\n                    _ext = _conf;\n                    return;\n                }\n                _midx[_id] = {\n                    ref:_conf.r,\n                    block:_conf.b\n                };\n            }\n        );\n        this.__setDataInCache(_prefix+'blen',_ext||[]);\n    };\n    /**\n     * 取索引块数据\n     * \n     * @protected\n     * @method module:util/cache/manager._$$StorageManager#__getIndex\n     * @return {Object} 索引块数据\n     */\n    _pro.__getIndex = function(){\n        return this.__getDataInCacheWithDefault(\n            this.__prefix+'index',{}\n        );\n    };\n    /**\n     * 取数据缓存集合，数据缓存\n     *\n     * @protected\n     * @method module:util/cache/manager._$$StorageManager#__getData\n     * @return {Object} 数据缓存集合\n     */\n    _pro.__getData = function(){\n        return this.__getDataInCacheWithDefault(\n            this.__prefix+'data',{}\n        );\n    };\n    /**\n     * 取块信息集合\n     *\n     * @protected\n     * @method module:util/cache/manager._$$StorageManager#__getBlock\n     * @return {Object} 块信息集合\n     */\n    _pro.__getBlock = function(){\n        return this.__getDataInCacheWithDefault(\n            this.__prefix+'block',[]\n        );\n    };\n    /**\n     * 取块信息集合\n     *\n     * @protected\n     * @method module:util/cache/manager._$$StorageManager#__getBlockLen\n     * @return {Object} 块信息集合\n     */\n    _pro.__getBlockLen = function(){\n        return this.__getDataInCacheWithDefault(\n            this.__prefix+'blen',[]\n        );\n    };\n    /**\n     * 分配块索引\n     *\n     * @protected\n     * @method module:util/cache/manager._$$StorageManager#__getBlockIndex\n     * @return {Number} 索引值\n     */\n    _pro.__getBlockIndex = function(){\n        var _result = -1,\n            _block = this.__getBlock(),\n            _list = this.__getBlockLen();\n        _u._$forIn(\n            _list,function(_length,_index){\n                var _arr = _block[_index];\n                // block loaded and length < block limit\n                if (!!_arr&&_arr.length<this.__limit){\n                    _result = _index;\n                    return !0;\n                }\n                // not load block and length < block limit\n                if (!_arr&&_length<this.__limit){\n                    this.__doLoadBlock(_index);\n                    // check real length\n                    if (_block[_index].length<this.__limit){\n                        _result = _index;\n                        return !0;\n                    }\n                }\n            },this\n        );\n        // new block index\n        if (_result<0){\n            _result = _list.length;\n            _list.push(0);\n            _block[_result] = [];\n        }\n        return _result;\n    };\n    /**\n     * 载入块数据\n     *\n     * @protected\n     * @method module:util/cache/manager._$$StorageManager#__doLoadBlock\n     * @return {Void}\n     */\n    _pro.__doLoadBlock = function(_bidx){\n        var _arr = [],\n            _hash = this.__getData(),\n            _index = this.__getIndex(),\n            _list = this.__getDataInStorage(this.__prefix+_bidx);\n        _u._$forEach(\n            _list,function(_data){\n                // sync data to index\n                var _tid = _data[this.__pkey],\n                    _conf = _index[_tid]||{};\n                _conf.block = _bidx;\n                _index[_tid] = _conf;\n                // cache data\n                _hash[_tid] = _data;\n                _arr.push(_tid);\n            },this\n        );\n        // cache block\n        this.__getBlock()[_bidx] = _arr;\n    };\n    /**\n     * 持久化索引块数据\n     *\n     * @protected\n     * @method module:util/cache/manager._$$StorageManager#__doFlushIndex\n     * @return {Void}\n     */\n    _pro.__doFlushIndex = function(){\n        // flush index\n        var _hash = {};\n        _u._$forIn(\n            this.__getIndex(),function(_conf,_id){\n                var _tmp = {b:_conf.block};\n                if (_conf.ref!=null){\n                    _tmp.r = _conf.ref;\n                }\n                _hash[_id] = _tmp;\n            }\n        );\n        // dump block attr\n        var _arr = [];\n        _u._$forEach(\n            this.__getBlock(),function(_list){\n                _arr.push(_list.length);\n            }\n        );\n        _hash[this.__prefix+'blen'] = _arr;\n        this.__setDataInStorage(this.__prefix+'index',_hash);\n    };\n    /**\n     * 持久化块数据\n     *\n     * @protected\n     * @method module:util/cache/manager._$$StorageManager#__doFlushBlock\n     * @param  {String|Array} arg0 - 块标识，没传表示序列化所有块\n     * @return {Void}\n     */\n    _pro.__doFlushBlock = function(_key){\n        var _map = this.__getBlock();\n        if (_key!=null){\n            if (!_u._$isArray(_key)){\n                var _arr = [];\n                _u._$forEach(\n                    _map[_key],function(_id){\n                        var _item = this._$get(_id);\n                        if (!!_item) _arr.push(_item);\n                    },this\n                );\n                this.__setDataInStorage(\n                    this.__prefix+_key,_arr\n                );\n            }else{\n                _u._$forEach(_key,this.__doFlushBlock,this);\n            }\n            return;\n        }\n        // flush all blocks\n        _u._$forIn(_map,function(_list,_key){\n            this.__doFlushBlock(_key);\n        },this);\n    };\n    /**\n     * 取单项数据或者列表数据\n     * \n     * @method module:util/cache/manager._$$StorageManager#_$get\n     * @param  {String|Array} arg0 - 项标识列表\n     * @return {Object|Array}        项数据列表\n     */\n    _pro._$get = function(_id){\n        // dump item\n        if (!_u._$isArray(_id)){\n            var _map = this.__getData();\n            // try to fetch from storage\n            if (!_map[_id]){\n                // 1 - check index\n                var _index = this.__getIndex(),\n                    _conf = _index[_id];\n                if (!_conf||_conf.block==null) return;\n                // 2 - check block loaded\n                var _bidx = _conf.block,\n                    _block = this.__getBlock();\n                if (!!_block[_bidx]) return;\n                // 3 - load data from storage\n                this.__doLoadBlock(_bidx);\n            }\n            return _map[_id];\n        }\n        // dump list\n        var _arr = [];\n        _u._$forEach(_id,function(_tid){\n            _arr.push(this._$get(_tid));\n        },this);\n        return _arr;\n    };\n    /**\n     * 添加数据\n     *\n     * @method module:util/cache/manager._$$StorageManager#_$add\n     * @param  {Object|Array} arg0 - 单个数据或列表\n     * @return {Void}\n     */\n    _pro._$add = (function(){\n        var _batch;\n        return function(_data){\n            var _bidx;\n            if (!_u._$isArray(_data)){\n                var _id = _data[this.__pkey],\n                    _item = this._$get(_id),\n                    _index = this.__getIndex();\n                // add ref and update data if exist\n                if (!!_item){\n                    var _conf = _index[_id],\n                        _ref = _conf.ref;\n                    _conf.ref = !_ref?1:(_ref+1);\n                    this._$update(_data);\n                    this.__doFlushIndex();\n                    return;\n                }\n                // add to cache\n                this.__getData()[_id] = _data;\n                _bidx = this.__getBlockIndex();\n                var _list = this.__getBlock()[_bidx];\n                if (_u._$indexOf(_list,_id)<0){\n                    _list.push(_id);\n                }\n                _index[_id] = {ref:1,block:_bidx};\n            }else{\n                _batch = [];\n                _u._$forEach(_data,this._$add,this);\n                _bidx = _batch;\n                _batch = null;\n            }\n            if (!!_batch){\n                if (_u._$indexOf(_batch,_bidx)<0){\n                    _batch.push(_bidx);\n                }\n                return;\n            }\n            // flush to storage\n            this.__doFlushIndex();\n            this.__doFlushBlock(_bidx);\n        };\n    })();\n    /**\n     * 删除数据\n     * \n     * @method module:util/cache/manager._$$StorageManager#_$delete\n     * @param  {String|Array} arg0 - 数据标识列表\n     * @return {Void}\n     */\n    _pro._$delete = (function(){\n        var _batch;\n        return function(_id){\n            if (!_u._$isArray(_id)){\n                // check data\n                var _data = this._$get(_id);\n                if (!_data) return;\n                // check data index\n                var _index = this.__getIndex(),\n                    _conf = _index[_id]||_o;\n                if (_conf.ref>1){\n                    // check ref\n                    _conf.ref--;\n                }else{\n                    // remove data from block list\n                    delete _index[_id];\n                    var _bidx = _conf.block,\n                        _list = this.__getBlock()[_bidx],\n                        _idx = _u._$indexOf(_list,_id);\n                    if (_idx>=0){\n                        _list.splice(_idx,1);\n                        if (!_batch){\n                            this.__doFlushBlock(_bidx);\n                        }else if(_u._$indexOf(_batch,_bidx)<0){\n                            _batch.push(_bidx);\n                        }\n                    }\n                }\n\n            }else{\n                _batch = [];\n                _u._$forEach(_id,this._$delete,this);\n                this.__doFlushBlock(_batch);\n                _batch = null;\n            }\n            if (!!_batch) return;\n            // flush to storage\n            this.__doFlushIndex();\n        };\n    })();\n    /**\n     * 更新数据\n     * \n     * @method module:util/cache/manager._$$StorageManager#_$update\n     * @param  {Object} arg0 - 数据对象\n     * @return {Void}\n     */\n    _pro._$update = function(_data){\n        var _id = _data[this.__pkey],\n            _item = this._$get(_id);\n        // add item\n        if (!_item){\n            this._$add(_item);\n            return;\n        }\n        // update item in cache\n        var _changed = !1;\n        NEJ.X(_item,_data,function(_value,_key){\n            _changed = _changed||(_value!==_item[_key]);\n        });\n        if (!_changed) return;\n        // flush block\n        var _index = this.__getIndex(),\n            _conf = _index[_id]||_o,\n            _bidx = _conf.block;\n        if (_bidx!=null){\n            this.__doFlushBlock(_bidx);\n        }\n    };\n    /**\n     * 迁移数据集，如果是数据列表直接使用_$add方法，\n     * 如果数据可能存在重复迁移则建议迁移后使用_$syncRef同步引用计数\n     * \n     * @method module:util/cache/manager._$$StorageManager#_$migrate\n     * @param  {Object} arg0 - 数据集\n     * @return {Void}\n     */\n    _pro._$migrate = function(_hash){\n        var _arr = [];\n        _u._$forIn(_hash,function(_item){\n            _arr.push(_item);\n        });\n        this._$add(_arr);\n    };\n    /**\n     * 同步引用计数\n     * \n     * @method module:util/cache/manager._$$StorageManager#_$syncRef\n     * @param  {Object} arg0 - ID对应的引用计数信息,{id:2}\n     * @return {Void}\n     */\n    _pro._$syncRef = function(_map){\n        var _index = this.__getIndex();\n        _u._$forIn(\n            _map,function(_ref,_id){\n                var _conf = _index[_id]||{};\n                _conf.ref = _ref;\n                _index[_id] = _conf;\n            },this\n        );\n        this.__doFlushIndex();\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/cache/platform/storage.js",
    "content": "/*\n * ------------------------------------------\n * 本地存储接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define(function(_p,_o,_f,_r){\n    /**\n     * 取缓存信息\n     * @param  {String} 缓存标识\n     * @return {String} 缓存信息\n     */\n    _p.__getItemInStorage = function(_key){\n        return localStorage.getItem(_key);\n    };\n    /**\n     * 设置缓存信息\n     * @param  {String} 缓存标识\n     * @param  {String} 缓存信息\n     * @return {Void}\n     */\n    _p.__setItemToStorage = function(_key,_value){\n        localStorage.setItem(_key,_value);\n    };\n    /**\n     * 删除缓存信息\n     * @param  {String} 缓存标识\n     * @return {Void}\n     */\n    _p.__removeItemFromStorage = function(_key){\n        localStorage.removeItem(_key);\n    };\n    /**\n     * 清除缓存\n     * @return {Void}\n     */\n    _p.__clearStorage = function(){\n        localStorage.clear();\n    };\n    /**\n     * 初始化本地存储系统\n     * @return {Void}\n     */\n    _p.__initStorage = function(){\n        (document.onstorageready||_f)();\n    };\n    /**\n     * 检测本地存储系统是否准备完毕\n     * @return {Boolean} 是否准备完毕\n     */\n    _p.__isStorageReady = function(){\n        return !0;\n    };\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/cache/platform/storage.patch.js",
    "content": "/*\n * ------------------------------------------\n * 本地存储接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/event',\n    './storage.js'\n],function(_v,_h,_p,_o,_f,_r){\n    // for ie7-\n    NEJ.patch('TR<=3.0',[\n        'base/config',\n        'util/flash/flash'\n    ],function(_c,_e){\n        var _localStorage;\n        /*\n         * 初始化本地存储系统\n         * @return {Void}\n         */\n        var _doInitFlash = function(){\n            if (!!_localStorage) return;\n            // append storage flash\n            _e._$flash({\n                hidden:!0,\n                src:_c._$get('storage.swf'),\n                params:{\n                    AllowScriptAccess:'sameDomain'\n                },\n                onready:function(_flash){\n                    if (!_flash){\n                        console.log('flash for localStorage unavailable');\n                    }else{\n                        _localStorage = _flash;\n                        _localStorage.initStorage('nej-storage');\n                    }\n                    _v._$dispatchEvent(document,'storageready');\n                }\n            });\n        };\n        /**\n         * 取缓存信息\n         * @param  {String} 缓存标识\n         * @return {String} 缓存信息\n         */\n        _h.__getItemInStorage = function(_key){\n            if (!!_localStorage){\n                return _localStorage.getItem(_key);\n            }\n        };\n        /**\n         * 设置缓存信息\n         * @param  {String} 缓存标识\n         * @param  {String} 缓存信息\n         * @return {Void}\n         */\n        _h.__setItemToStorage = function(_key,_value){\n            if (!!_localStorage){\n                _localStorage.setItem(_key,_value);\n            }\n        };\n        /**\n         * 删除缓存信息\n         * @param  {String} 缓存标识\n         * @return {Void}\n         */\n        _h.__removeItemFromStorage = function(_key){\n            if (!!_localStorage){\n                _localStorage.removeItem(_key);\n            }\n        };\n        /**\n         * 清除缓存\n         * @return {Void}\n         */\n        _h.__clearStorage = function(){\n            if (!!_localStorage){\n                _localStorage.clear();\n            }\n        };\n        /**\n         * 初始化本地存储系统\n         * @return {Void}\n         */\n        _h.__initStorage = function(){\n            _doInitFlash();\n        };\n        /**\n         * 检测本地存储系统是否准备完毕\n         * @return {Boolean} 是否准备完毕\n         */\n        _h.__isStorageReady = function(){\n            return !!_localStorage;\n        };\n    });\n    \n    return _h;\n});\n"
  },
  {
    "path": "src/util/cache/share.js",
    "content": "/*\n * ------------------------------------------\n * 临时内存数据共享管理实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/cache/share */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    'util/event'\n],function(NEJ,_k,_u,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 临时内存数据共享管理器\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/cache/share'\n     * ],function(_t){\n     *     // 重新开辟共享存储空间\n     *     var _share = _t._$$CacheShare._$allocate({\n     *         oncachechange:function(_event){\n     *             // _event.key\n     *             // _event.type\n     *             // _event.oldValue\n     *             // _event.newValue\n     *             \n     *             // TODO\n     *         }\n     *     });\n     * \n     *     // 写入数据\n     *     _share._$set('abc',{a:'aaaaa',b:'bbbbbb'});\n     *     // 读取数据\n     *     var _data = _share._$get('abc');\n     *     // 删除数据\n     *     _share._$remove('abc');\n     * });\n     * ```\n     * \n     * @class   module:util/cache/share._$$CacheShare\n     * @extends module:util/event._$$EventTarget\n     */\n    /** \n     * 缓存变化出发事件\n     * \n     * @event    module:util/cache/share._$$CacheShare#oncachechange\n     * @param    {Object}   event    - 事件信息\n     * @property {String}   key      - 缓存标识\n     * @property {String}   type     - 操作类型，set/delete\n     * @property {Variable} oldValue - 原数据\n     * @property {Variable} newValue - 新数据\n     */\n    _p._$$CacheShare = _k._$klass();\n    _pro = _p._$$CacheShare._$extend(_t._$$EventTarget);\n    /**\n     * 初始化函数\n     * \n     * @protected\n     * @method module:util/cache/share._$$CacheShare#__init\n     * @return {Void}\n     */\n    _pro.__init = (function(){\n        var _seed = +new Date,\n            _ckey = 'dat-'+_seed;\n        return function(){\n            this.__super();\n            var _cache = this.constructor[_ckey];\n            if (!_cache){\n                _cache = {};\n                this.constructor[_ckey] = _cache;\n            }\n            this.__cache = _cache;\n        };\n    })();\n    /**\n     * 取缓存数据\n     * \n     * @method module:util/cache/share._$$CacheShare#_$get\n     * @param  {Object}   arg0 - 缓存标识\n     * @return {Variable}        缓存数据\n     */\n    _pro._$get = function(_key){\n        return this.__cache[_key];\n    };\n    /**\n     * 设置缓存数据\n     * \n     * @method module:util/cache/share._$$CacheShare#_$set\n     * @param  {String}   arg0 - 缓存标识\n     * @param  {Variable} arg1 - 缓存数据\n     * @return {Void}\n     */\n    _pro._$set = function(_key,_value){\n        var _old = this.__cache[_key];\n        this.__cache[_key] = _value;\n        this._$dispatchEvent(\n            'oncachechange',{\n                key:_key,\n                type:'set',\n                oldValue:_old,\n                newValue:_value\n            }\n        );\n    };\n    /**\n     * 删除缓存项\n     *\n     * @method module:util/cache/share._$$CacheShare#_$remove\n     * @param  {String}   arg0 - 缓存标识\n     * @return {Variable}        删除项的值\n     */\n    _pro._$remove = function(_key){\n        var _old = this.__cache[_key];\n        _u._$safeDelete(this.__cache,_key);\n        this._$dispatchEvent(\n            'oncachechange',{\n                key:_key,\n                type:'delete',\n                oldValue:_old,\n                newValue:undefined\n            }\n        );\n        return _old;\n    };\n    /**\n     * 查询指定名字空间路径的值\n     *\n     * @method module:util/cache/share._$$CacheShare#_$query\n     * @param  {String}   arg0 - 查询串，如：a.b.c\n     * @return {Variable}        结果\n     */\n    _pro._$query = function(_namespace){\n        return _u._$query(this.__cache,_namespace);\n    };\n    /**\n     * 系统统一共享内存存储空间\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/cache/share'\n     * ],function(_t){\n     *     // 使用系统统一存储空间\n     *     var _localCache = _t.localCache;\n     *     // 添加缓存变化监测事件\n     *     _localCache._$addEvent(\n     *         'oncachechange',function(_event){\n     *             // _event.key\n     *             // _event.type\n     *             // _event.oldValue\n     *             // _event.newValue\n     *\n     *             // TODO\n     *         }\n     *     );\n     * \n     *     // 写入数据\n     *     _localCache._$set('abc',{a:'aaaaa',b:'bbbbbb'});\n     *     // 读取数据\n     *     var _data = _localCache._$get('abc');\n     *     // 删除数据\n     *     _localCache._$remove('abc');\n     * });\n     * ```\n     *\n     * @static\n     * @member {module:util/cache/share._$$CacheShare} localCache\n     */\n    _p.localCache = _p._$$CacheShare._$allocate();\n    \n    if (CMPT){\n        this.localCache = _p.localCache;\n        NEJ.P('nej.ut')._$$ShareCache = _p._$$CacheShare;\n    }\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/cache/storage.js",
    "content": "/*\n * ------------------------------------------\n * 本地存储接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/cache/storage */\nNEJ.define([\n    'base/global',\n    'base/util',\n    'base/event',\n    'util/event/event',\n    'util/encode/json',\n    '{platform}storage.js'\n],function(NEJ,_u,_v,_t,_j,_h,_p,_o,_f,_r){\n    var _cache = {}; // dirty flag\n    /**\n     * 初始化低版本浏览器本地缓存\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/cache/storage'\n     * ],function(_j){\n     *     // 如果需要支持ie7-浏览器先执行一下初始行为\n     *     _j._$init();\n     *     // 设置一个hash值\n     *     _j._$setDataInStorage('name','jack');\n     *     // 返回jack\n     *     var _data = _j._$getDataInStorage('name');\n     * });\n     * ```\n     *\n     * @method module:util/cache/storage._$init\n     * @return {Void}\n     */\n    _p._$init = (function(){\n        var inited = !1;\n        return function(){\n            if (inited){\n                return;\n            }\n            inited = !0;\n            // listen storage ready\n            var __doFlushTempData = (function(){\n                var _doFlush = function(_value,_key,_map){\n                    _h.__setItemToStorage(\n                        _key,JSON.stringify(_value));\n                    delete _map[_key];\n                };\n                return function(){\n                    _u._$loop(_cache,_doFlush);\n                };\n            })();\n            _v._$addEvent(\n                document,'storageready',\n                __doFlushTempData\n            );\n            // init storage\n            _h.__initStorage();\n        };\n    })();\n    /**\n     * 存储数据\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/cache/storage'\n     * ],function(_j){\n     *     // 设置一个hash值\n     *     _j._$setDataInStorage('name','jack');\n     *     // 返回jack\n     *     var _data = _j._$getDataInStorage('name');\n     * });\n     * ```\n     *\n     * @method module:util/cache/storage._$setDataInStorage\n     * @see    module:util/cache/storage._$getDataInStorage\n     * @param  {String}   arg0 - 存储键值\n     * @param  {Variable} arg1 - 存储数据\n     * @return {Void}\n     */\n    _p._$setDataInStorage = function(_key,_value){\n        _p._$init();\n        var _sval = JSON.stringify(_value);\n        try{\n            _h.__setItemToStorage(_key,_sval);\n        }catch(ex){\n            console.error(ex.message);\n            console.error(ex);\n        }\n        // set failed\n        if (_sval!=_h.__getItemInStorage(_key)){\n            _cache[_key] = _value;\n        }\n    };\n    /**\n     * 取存储数据\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/cache/storage'\n     * ],function(_j){\n     *     // 设置一个hash值\n     *     _j._$setDataInStorage('name','jack');\n     *     // 返回jack\n     *     var _data = _j._$getDataInStorage('name');\n     * });\n     * ```\n     *\n     * @method module:util/cache/storage._$getDataInStorage\n     * @see    module:util/cache/storage._$setDataInStorage\n     * @param  {String}   arg0 - 存储键值\n     * @return {Variable}        存储数据\n     */\n    _p._$getDataInStorage = function(_key){\n        _p._$init();\n        var _data = JSON.parse(\n            _h.__getItemInStorage(_key)||'null'\n        );\n        return _data==null?_cache[_key]:_data;\n    };\n    /**\n     * 取存储数据，如果指定的数据不存在则使用默认数据初始化\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/cache/storage'\n     * ],function(_j){\n     *     // 取key为name的值，没有则设置一个key为name，value为jack的值\n     *     var _data = _j._$getDataInStorageWithDefault('name','jack');\n     * });\n     * ```\n     *\n     * @method module:util/cache/storage._$getDataInStorageWithDefault\n     * @see    module:util/cache/storage._$setDataInStorage\n     * @see    module:util/cache/storage._$getDataInStorage\n     * @param  {String}   arg0 - 存储键值\n     * @param  {Variable} arg1 - 存储数据\n     * @return {Variable}        存储数据\n     */\n    _p._$getDataInStorageWithDefault = function(_key,_value){\n        var _data = _p._$getDataInStorage(_key);\n        if (_data==null){\n            _data = _value;\n            _p._$setDataInStorage(_key,_data);\n        }\n        return _data;\n    };\n    /**\n     * 删除本地存储数据\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'util/cache/storage'\n     *   ],function(_j){\n     *       _j._$setDataInStorage('name','jack');\n     *       // 删除key为name的hash值\n     *       _j._$delDataInStorage('name');\n     *   });\n     * ```\n     *\n     * @method module:util/cache/storage._$delDataInStorage\n     * @param  {String} arg0 - 存储键值\n     * @return {Void}\n     */\n    _p._$delDataInStorage = function(_key){\n        _p._$init();\n        delete _cache[_key];\n        _h.__removeItemFromStorage(_key);\n    };\n    /**\n     * 清除本地缓存\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/cache/storage'\n     * ],function(_p){\n     *     _p._$setDataInStorage('name','jack');\n     *     // 清空所有hash值\n     *     _p._$clearDataInStorage();\n     * });\n     * ```\n     *\n     * @method module:util/cache/storage._$clearDataInStorage\n     * @return {Void}\n     */\n    _p._$clearDataInStorage = (function(){\n        var _doRemove = function(_item,_key,_map){\n            delete _map[_key];\n        };\n        return function(){\n            _p._$init();\n            _u._$loop(_cache,_doRemove);\n            _h.__clearStorage();\n        };\n    })();\n    /**\n     * 持久化存储器准备完毕触发事件，\n     * 如果存储器已准备完毕则在添加事件时直接触发回调\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/event'\n     *     'util/cache/storage'\n     * ],function(_v,_j){\n     *     // 直接调用接口存储数据在低版本浏览器下未能保证持久化成功\n     *     // 如果此时持久化存储器未准备完毕则先缓存在内存中，等持久化存储器准备好后再持久化\n     *     _j._$setDataInStorage('name','jack');\n     *\n     *     // 在持久化存储器准备完毕事件中存储数据可提高持久化成功概率\n     *     _v._$addEvent(\n     *         document,'storageready',\n     *         function(_event){\n     *             _j._$setDataInStorage('name','jack');\n     *         }\n     *     );\n     * });\n     * ```\n     *\n     * @event    external:document.onstorageready\n     * @param    {Object} event - 事件信息\n     */\n    _t._$$CustomEvent._$allocate({\n        element:document,\n        event:'storageready',\n        oneventadd:function(){\n            if (_h.__isStorageReady()){\n                _v._$dispatchEvent(document,'storageready');\n            }\n        }\n    });\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.j'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/cache/test/cache.custom.js",
    "content": "var f = function(){\n\tvar _  = NEJ.P,\n        _f = NEJ.F,\n        _u = _('nej.u'),\n        _e = _('nej.e'),\n        _p = _('nej.ut'),\n\t\t_j = _('nej.j'),\n        _proCacheCustom;\n\t_p._$$CacheCustom = NEJ.C();\n    _proCacheCustom = _p._$$CacheCustom._$extend(_p._$$CacheAbstract);\n\n\t_proCacheCustom.__reset = function(_options){\n\t\tthis.__supReset(_options);\n\t\tthis.__getCache(_options._id);\n\t};\n\n\t_proCacheCustom.__getCache = function(_id){\n\t\tvar _cache = {};\n\t\tif (!!_id){\n            _cache = this.__cache[_id];\n            if (!_cache){\n                _cache = {};\n                this.__cache[_id] = _cache;\n            }\n        }\n\t\tthis.__myCache = _cache;\n\t};\n\n\t/**\n\t * 从cache中获取数据\n\t * @param {Object} _id\n\t */\n\t_proCacheCustom._$getItemInCache = function(_rkey){\n\t\t// 这里去缓存中拿\n\t\treturn this.__myCache[_rkey];\n\t}\n\n\t/**\n\t * 对外保留的获取数据接口\n\t */\n\t_proCacheCustom._$getData = (function(){\n\t\treturn function(_id,_key){\n            var _rkey = _id+_key;\n            var _ropt = {id:_id,key:_key||''},\n                _item = this._$getItemInCache(_rkey);\n            if (!!_item){\n                this._$dispatchEvent('ondataload',_ropt);\n                return this;\n            }\n            if (!this.__doQueueRequest(_rkey,\n                 this._$dispatchEvent._$bind(this,'ondataload'))){\n                _ropt.rkey = _rkey;\n                _ropt.onload = this.__getData._$bind(this,_ropt);\n                this._$dispatchEvent('dodataload',_ropt);\n            }\n            return this;\n        };\n\t})();\n\n\t_proCacheCustom.__doSaveToCache = function(_rkey,_data){\n\t\tif(!this.__myCache[_rkey])\n\t\t  this.__myCache[_rkey] = _data;\n\t}\n\n\t/**\n\t * 请求返回数据后处理\n\t * @param {Object} _ropt\n\t * @param {Object} _data\n\t */\n\t_proCacheCustom.__getData = function(_ropt,_data){\n\t\t_ropt = _ropt||_o;\n\t\t// 这里缓存到列表中去\n        this.__doSaveToCache(_ropt.rkey,_data);\n        this.__doCallbackRequest(_ropt.rkey,_ropt);\n\t};\n}\ndefine('{pro}cache.custom.js',['{lib}util/cache/cache.js'],f);\n"
  },
  {
    "path": "src/util/cache/test/cache.list.custom.js",
    "content": "var f = function(){\n    var _  = NEJ.P,\n        _f = NEJ.F,\n        _u = _('nej.u'),\n        _e = _('nej.e'),\n        _p = _('nej.ut'),\n        _j = _('nej.j'),\n        _v = _('nej.v'),\n        _proCacheListCustom;\n    _p._$$CacheListCustom = NEJ.C();\n    _proCacheListCustom = _p._$$CacheListCustom._$extend(_p._$$AbstractListCache);\n\n\t_proCacheListCustom.__doLoadList = function(_options){\n\t\tvar _key    = _options.key;\n\t\tvar _data   = _options.data;\n\t\tvar _offset = _options.offset;\n\t\tvar _limit  = _options.limit;\n\t\tvar _rkey   = _options.rkey;\n\t\tvar _onload = _options.onload;\n        // for test\n        var _arr = [];\n        var _len = _options.offset>=30?4:_options.limit;\n        for(var i=0;i<_len;i++){\n            _arr.push({id:+new Date+i,name:'user-'+(+new Date +i),loginTime:+new Date});\n        }\n        if (_options.offset==0){\n            this._$setTotal(_options.key,34);\n        }\n        window.setTimeout(_options.onload._$bind(_options,_arr),1000);\n//\t\t_j._$request('http://123.163.com:3000/xhr/getLog',{\n//                type:'json',\n//                method:'POST',\n//                data:{offset:_offset,limit:_limit},\n//                timeout:1000,\n//                onload:_onload._$bind(this),\n//                onerror:function(_error){\n//\t\t\t\t}\n//            }\n//        );\n\t};\n\n\t/**\n     * 从服务器中获取一项\n     * @param {Object} _options\n     */\n\t_proCacheListCustom.__doLoadItem = function(_options){\n        var _id     = _options.id;\n        var _key    = _options.key;\n        var _rkey   = _options.rkey;\n        var _onload = _options.onload;\n        _j._$request('http://123.163.com:3000/xhr/getLog',{\n                type:'json',\n                method:'POST',\n                data:{rkey:_rkey},\n                timeout:1000,\n                onload:_onload._$bind(this),\n                onerror:function(_error){}\n            }\n        );\n    };\n\n    /**\n     * 增加一项到服务器\n     * @param {Object} _options\n     */\n\t_proCacheListCustom.__doAddItem = function(_options){\n        var _key  = _options.key;\n        var _item = _options.item;\n\t\tvar _push = _options.push;\n        var _onload = _options.onload;\n        _j._$request('http://123.163.com:3000/xhr/getLog',{\n                type:'json',\n                method:'POST',\n                data:{},\n                timeout:1000,\n                onload:_onload._$bind(this),\n                onerror:function(_error){}\n            }\n        );\n    };\n\n\t/**\n     * 从服务器中删除一项\n     * @param {Object} _options\n     */\n\t_proCacheListCustom.__doDeleteItem = function(_options){\n        // var _id     = _options.id;\n        // var _key    = _options.key;\n        // var _rkey   = _options.rkey;\n        // var _onload = _options.onload;\n        // _j._$request('http://123.163.com:3000/xhr/getLog',{\n        //         type:'json',\n        //         method:'POST',\n        //         data:{rkey:_rkey},\n        //         timeout:1000,\n        //         onload:_onload._$bind(this),\n        //         onerror:function(_error){}\n        //     }\n        // );\n        // for test\n        window.setTimeout(function(){\n            var _event = _options.onload(!0);\n            // _v._$dispatchEvent(\n            //     _p._$$CacheListCustom,'listchange',_event);\n        },500);\n    };\n\n\t/**\n     * 更新服务器中的一项\n     * @param {Object} _options\n     */\n\t_proCacheListCustom.__doUpdateItem = function(_options){\n        var _id     = _options.id;\n        var _key    = _options.key;\n        var _rkey   = _options.rkey;\n        var _onload = _options.onload;\n        _j._$request('http://123.163.com:3000/xhr/getLog',{\n                type:'json',\n                method:'POST',\n                data:{rkey:_rkey},\n                timeout:1000,\n                onload:_onload._$bind(this),\n                onerror:function(_error){}\n            }\n        );\n    };\n\n}\ndefine('{pro}cache.list.custom.js',['{lib}util/event/event.js','{lib}util/cache/abstract.js'],f);\n\n"
  },
  {
    "path": "src/util/cache/test/cache.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>cache测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit cache test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n \t\t<script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./cache.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/util/cache/test/cache.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"cache&&cookie&&storage\");\n    var c = NEJ.P('nej.ut'),\n\t    j = NEJ.P('nej.j');\n\t    \n    //开始单元测试\n//    test('setEvent', function() {\n//        stop();\n//        var _i = 0;\n//        var _f = function(){\n//            _i =1;\n//        }\n//        var _obj = new c._$$CacheAbstract();\n//        _obj._$setEvent('clickxxx',_f);\n//        _obj._$dispatchEvent('clickxxx');\n//        equal(_i,1,'clickxxx方法被成功调用');\n//        start();\n//    });\n//    \n//    test('setEvent,带参数的回调', function() {\n//        stop();\n//        var _i = 0;\n//        var _f = function(_num){\n//            _i = _num;\n//        }\n//        var _obj = new c._$$CacheAbstract();\n//        _obj._$setEvent('click',_f);\n//        _obj._$dispatchEvent('click',5);\n//        equal(_i,5,'方法被成功调用,并且设置的值正确');\n//        start();\n//    });\n//    \n//    test('batEvent,批量设置事件', function() {\n//        stop();\n//        var _i = 0;\n//        var _f0 = function(_num){\n//            _i = _num;\n//        }\n//        var _f1 = function(){\n//            \n//        };\n//        var _obj = new c._$$CacheAbstract();\n//        _obj._$batEvent(\n//            {\n//                f0:_f0._$bind(this),\n//                f1:_f1._$bind(this)\n//            }\n//        );\n//        _obj._$dispatchEvent('f0',50);\n//        equal(_i,50,'方法被成功调用,并且设置的值正确');\n//        start();\n//    });\n//    \n//    test('hasEvent,检查是否有某类事件', function() {\n//        stop();\n//        var _i = 0;\n//        var _f0 = function(_num){\n//            _i = _num;\n//        }\n//        var _obj = new c._$$CacheAbstract();\n//        _obj._$setEvent('f0',_f0);\n//        equal(_obj._$hasEvent('f0'),true,'检查有f0这个事件');\n//        start();\n//    });\n//    \n//    test('clearEvent,检查是否有某类事件', function() {\n//        stop();\n//        var _i = 0;\n//        var _f0 = function(_num){\n//            _i = _num;\n//        }\n//        var _obj = new c._$$CacheAbstract();\n//        _obj._$setEvent('f0',_f0);\n//        _obj._$clearEvent('f0')\n//        equal(_obj._$hasEvent('f0'),false,'f0被清除了');\n//        start();\n//    });\n//    \n//    test('api,在API中分配控件实例，如果指定ID已存在当前控件的实例则直接返回', function() {\n//        stop();\n//        var _obj = new c._$$CacheAbstract();\n//        var _id= 'widget0';\n//        var _cache = nej.ut._$api(_id,c._$$CacheAbstract,{});\n//        equal(typeof(_cache),'object','分配一个实例控件');\n//        var _flag = nej.ut._$api(_id,c._$$CacheAbstract);\n//        equal(typeof(_flag),'object','第3个参数未传，只检查是否有实例存在，有直接放回');\n//        var _flag2 = nej.ut._$api('widget1',c._$$CacheAbstract);\n//        equal(_flag2,undefined,'第3个参数未传，只检查是否有实例存在，有直接放回');\n//        start();\n//    });\n//    \n//    test('setEvent,带参数的回调,type为oncachechange', function() {\n//        stop();\n//        var _i = 0;\n//        var _f = function(_num){\n//            _i = _num;\n//        }\n//        var _obj = new c._$$CacheAbstract();\n//        _obj._$setEvent('oncachechange',_f);\n//        _obj._$dispatchEvent('oncachechange',10);\n//        equal(_i,10,'oncachechange方法被成功调用,并且设置的值正确');\n//        start();\n//    });\n//    \n//    test('cookie value',function(){\n//        var j = NEJ.P('nej.j');\n//        var _cookie = j._$cookie(\"name\",{value:'chenglin'});\n//        equal(j._$cookie('name'),'chenglin','cookie设置成功');\n//    });\n//    \n//    test('cookie value expires',function(){\n//        var j = NEJ.P('nej.j');\n//        var _cookie = j._$cookie(\"name1\",{value:'chenglin1',expires:1});\n//        stop();\n//        setTimeout(function(){\n//            equal(j._$cookie('name1'),'chenglin1','cookie设置成功，时间过期');start()},500);\n//    });\n//\t\n//\ttest('cookie value expires delete cookie',function(){\n//        var j = NEJ.P('nej.j');\n//\t\tvar _cookie = j._$cookie(\"namedd\",{value:'chenglin123',expires:1});\n//        var _cookie = j._$cookie(\"namedd\",{expires:-1});\n//        stop();\n//        setTimeout(function(){\n//            equal(j._$cookie('namedd'),'','cookie 被删除');start()},500);\n//    });\n//    \n//    test('cookie value path expires x',function(){\n//        var j = NEJ.P('nej.j');\n//        var _cookie = j._$cookie(\"name2\",{value:'chenglin2',path:'/',expires:1});\n//        stop();\n//        setTimeout(function(){\n//            equal(j._$cookie('name2'),'chenglin2','cookie设置成功，时间过期');start()},500);\n//    });\n//    \n//    test('cookie value path domain expires',function(){\n//        var j = NEJ.P('nej.j');\n//        var _cookie = j._$cookie(\"name3\",{value:'chenglin3',path:'/',domain:'www.baidu.com',expires:1});\n//        stop();\n//\t\tsetTimeout(function(){\n//            notEqual(j._$cookie('name3'),'chenglin3','cookie设置成功，时间过期,domain不是同域名，设置cookie失败');start()},500);\n//    });\n//    \n//    test('_$setDataInStorage',function(){\n//        var j = NEJ.P('nej.j');\n//        j._$setDataInStorage('name','jack');\n//        equal(j._$getDataInStorage('name'),'jack','本地存储localstorage');\n//    });\n//    \n//    test('localstorage然后删除',function(){\n//        var j = NEJ.P('nej.j');\n//        j._$setDataInStorage('name','jack');\n//        j._$delDataInStorage('name');\n//        equal(j._$getDataInStorage('name'),null,'本地存储localstorage,然后删除');\n//    });\n//    \n//    test('localstorage，删除后用默认数据',function(){\n//        var j = NEJ.P('nej.j');\n//        j._$setDataInStorage('name','jack');\n//        j._$delDataInStorage('name');\n//        equal(j._$getDataInStorage('name'),null,'本地存储localstorage,然后删除');\n//        equal(j._$getDataInStorageWithDefault('name','default'),'default','本地存储localstorage,然后删除,数据不存在用默认数据')\n//    });\n//    \n//    test('localstorage清除所有数据',function(){\n//        var j = NEJ.P('nej.j');\n//        j._$setDataInStorage('name','jack');\n//        j._$setDataInStorage('name1','jack1');\n//        j._$clearDataInStorage();\n//        equal(j._$getDataInStorage('name'),null,'本地存储localstorage,清除所有数据');\n//        equal(j._$getDataInStorage('name1'),null,'本地存储localstorage,清除所有数据');\n//    });\n//\t\n//\t test('localstorage克隆一份数据',function(){\n//        var j = NEJ.P('nej.j');\n//        j._$setDataInStorage('name','jack');\n//        j._$setDataInStorage('name1','jack1');\n//        var _result = j._$cloneDataInStorage({name:'',name1:''});\n//\t\tequal(_result['name'],'jack','成功复制数据');\n//    });\n//\t\n//\ttest('cache request',function(){\n//\t\tstop();\n//\t\tvar _cc = c._$$CacheCustom._$allocate({\n//\t\t\tondataload: function(_ropt){\n//\t\t\t\tok(true,'最终的数据处理');\n//                start();\n//\t\t\t},\n//\t\t\tdodataload:function(_ropt){\n//                j._$request('http://123.163.com:3000/xhr/getLog',{\n//\t                    type:'json',\n//\t                    method:'POST',\n//\t                    data:{name:'cheng-lin'},\n//\t                    timeout:1000,\n//\t                    onload:_ropt.onload._$bind(this),\n//\t                    onerror:function(_data){\n//                        \n//                        }\n//                    }\n//                );\n//            }\n//\t\t})\n//\t\t_cc._$getData('a','b');\n//\t\t_cc._$getData('a','c');\n//\t\t_cc._$getData('a','b');\n//\t});\n\t\n\ttest('cache list request',function(){\n\t\tstop();\n\t\tvar _cc = c._$$CacheListCustom._$allocate({\n\t\t\tid:'a',\n\t\t\tonlistload:function(_ropt){\n\t\t\t\tok(true,'获取列表数据的回调');\n\t\t\t\tstart();\n\t\t\t},\n\t\t\tonitemload:function(_ropt){\n                ok(true,'获取项数据的回调');\n\t\t\t\tstart();\n            },\n\t\t\tonitemupdate:function(_item,_key){\n\t\t\t\tok(true,'更新项数据的回调');\n\t\t\t\tstart();\n\t\t\t},\n\t\t\tonitemdelete:function(_item,_key){\n\t\t\t\tok(true,'删项数据的回调');\n\t\t\t\tstart();\n\t\t\t},\n\t\t\tonitemadd:function(_item,_key){\n\t\t\t\tok(true,'增加项数据的回调');\n\t\t\t\tstart();\n\t\t\t}\n\t\t});\n\t\t_cc._$getList({key:'abc',data:{},offset:0,limit:10})\n\t\t_cc._$getList({key:'abc',data:{},offset:0,limit:10})\n\t\t_cc._$getItem({id:'abc',key:'123',data:{}})\n\t\t_cc._$addItem({\n\t\t\tkey: '123',\n\t\t\titem: {},\n\t\t\tpush: false\n\t\t});\n\t\t_cc._$updateItem({\n\t\t\tkey:'123',\n\t\t\titem:{}\n\t\t});\n\t\t_cc._$deleteItem({\n\t\t\tkey:'123',\n\t\t\tid:'abc'\n\t\t});\n\t});\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}cache.test.js',['{pro}cache.custom.js',\n    \t  '{pro}cache.list.custom.js',\n    \t  '{lib}util/ajax/xdr.js',\n    \t  '{lib}util/cache/cache.js',\n    \t  '{lib}util/cache/cookie.js',\n    \t  '{lib}util/cache/storage.js'],f);\n});\n  "
  },
  {
    "path": "src/util/cache/test/cookie.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>cookie测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit cookie test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./cookie.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/cache/test/cookie.test.js",
    "content": "NEJ.define(['util/cache/cookie'],function(_j){\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v');\n    test('cookie',function(){\n        expect(1);\n        _j._$cookie('name',{value:'abc'});\n        equal(_j._$cookie('name'),'abc','set cookie 成功');\n    });\n\n    test('cookie',function(){\n        expect(1);\n        _j._$cookie('name','');\n        _j._$cookie('name',{expires:-1});\n        equal(_j._$cookie('name'),'','delete cookie 成功');\n    });\n\n     test('cookie',function(){\n        expect(1);\n        var _cookie = _j._$cookie('name2',{\n               value:'abc',\n               path:'/',\n               domain:'nei.hz.netease.com',\n               expires:1\n           });\n        equal(_j._$cookie('name2'),'abc','name2 set cookie 成功');\n    });\n});"
  },
  {
    "path": "src/util/cache/test/storage.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>storage测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit storage test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./storage.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/cache/test/storage.test.js",
    "content": "NEJ.define(['util/cache/storage','util/encode/json'],function(_t){\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v');\n    test('storage',function(){\n        expect(1);\n        _t._$setDataInStorage('a','b');\n        equal(_t._$getDataInStorage('a'),'b','storage --set，get成功');\n    });\n    test('storage',function(){\n        expect(1);\n        equal(_t._$getDataInStorageWithDefault('ccc','ccc'),'ccc','有默认数据')\n    });\n    test('storage',function(){\n        expect(1);\n        _t._$delDataInStorage('a','b');\n        equal(_t._$getDataInStorage('a'),undefined,'storage --set，get成功');\n    });\n});"
  },
  {
    "path": "src/util/calendar/calendar.js",
    "content": "/*\n * ------------------------------------------\n * 日历算法实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/calendar/calendar */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'base/util',\n    'util/event'\n],function(NEJ,_k,_e,_v,_u,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 日历算法\n     *\n     * 日期范围说明\n     *\n     * | 范围 | 说明 |\n     * | :--- | :--- |\n     * | [0,0]                                   | 全部日期可选【默认】 |\n     * | [0,new Date]                            | 可选当前日期之前的 |\n     * | [new Date,0]                            | 可选当前日期之后的 |\n     * | [new Date(1997,1,1),new Date(2000,1,1)] | 可选指定范围的日期 |\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"datepick-box\">\n     *   <div id=\"days\"></div>\n     *   <div id=\"year\"></div>\n     *   <div id=\"month\"></div>\n     *   <div id=\"yprv\">前一年</div>\n     *   <div id=\"mprv\">前一月</div>\n     *   <div id=\"ynxt\">后一年</div>\n     *   <div id=\"mnxt\">后一月</div>\n     * </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/calendar/calendar'\n     * ],function(_t){\n     *     // 构建日期列表\n     *     var _days = _e._$get('days');\n     *     _html = _e._$add('{list 1..2 as x}<div>{list 1..6 as y}<p class=\"z-day\"></p>{/list}</div>{/list}');\n     *     _days.innerHTML = _e._$get(_html);\n     *     // 分配日历功能\n     *     var _calendar = _t._$$Calendar._$allocate({\n     *         parent:'datepick-box',\n     *         list:_e._$getByClassName(_days,\"z-day\"),\n     *         offset:1,\n     *         year:'year',\n     *         month:'month',\n     *         yprv:'yprv',\n     *         mprv:'mprv',\n     *         ynxt:'ynxt',\n     *         mnxt:'mnxt',\n     *         // 日期的范围，超过范围不可选\n     *         range:[new Date(2011,7,9),new Date(2013,7,9)],\n     *         onchange:function(_date){\n     *             // 日期列表变化\n     *         },\n     *         onselect:function(_date){\n     *             // 选择了一个日期，返回此日期\n     *         }\n     *     });\n     *   \n     * });\n     * ```\n     * \n     * @class    module:util/calendar/calendar._$$Calendar\n     * @extends  module:util/event._$$EventTarget\n     *\n     * @param    {Object}      config   - 可选配置参数\n     * @property {Number}      offset   - 开始星期偏移，默认为0，0-星期天、1-星期一 ...\n     * @property {Array}       list     - 日期显示节点列表\n     * @property {Number}      year     - 年份显示节点\n     * @property {Number}      month    - 月份显示节点\n     * @property {String|Node} mprv     - 上一月按钮节点\n     * @property {String|Node} mnxt     - 下一月按钮节点\n     * @property {String|Node} yprv     - 上一年按钮节点\n     * @property {String|Node} ynxt     - 下一年按钮节点\n     * @property {String|Node} wprv     - 上一星期按钮节点\n     * @property {String|Node} wnxt     - 下一星期按钮节点\n     * @property {String|Node} dprv     - 上一天按钮节点\n     * @property {String|Node} dnxt     - 下一天按钮节点\n     * @property {Array}       range    - 日期可选范围，默认全部可选\n     * @property {String}      selected - 当前项样式，默认为js-selected\n     * @property {String}      extended - 扩展项样式，默认为js-extended\n     * @property {String}      disabled - 禁用项样式，默认为js-disabled\n     * @property {Date}        date     - 显示日期，默认为当前时间\n     */\n    /**\n     * 日期变化事件\n     * \n     * @event module:util/calendar/calendar._$$Calendar#onchange\n     * @param {Date} date - 当前日期\n     */\n    /**\n     * 日期选中事件\n     * \n     * @event module:util/calendar/calendar._$$Calendar#onselect\n     * @param {Date} date - 选中日期\n     */\n    _p._$$Calendar = _k._$klass();\n    _pro = _p._$$Calendar._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/calendar/calendar._$$Calendar#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        // init event\n        // TODO delegate event\n        this.__doInitDomEvent([[\n            _options.mprv,'click',\n            this.__onMonthChange._$bind(this,-1)\n        ],[\n            _options.mnxt,'click',\n            this.__onMonthChange._$bind(this, 1)\n        ],[\n            _options.yprv,'click',\n            this.__onYearChange._$bind(this,-1)\n        ],[\n            _options.ynxt,'click',\n            this.__onYearChange._$bind(this, 1)\n        ],[\n            _options.wprv,'click',\n            this.__onWeekChange._$bind(this,-1)\n        ],[\n            _options.wnxt,'click',\n            this.__onWeekChange._$bind(this, 1)\n        ],[\n            _options.wprv,'click',\n            this.__onDayChange._$bind(this,-1)\n        ],[\n            _options.wnxt,'click',\n            this.__onDayChange._$bind(this, 1)\n        ]]);\n        this.__offset = _options.offset||0;\n        this.__nyear  = _e._$get(_options.year);\n        this.__nmonth = _e._$get(_options.month);\n        this.__selected = _options.selected||'js-selected';\n        this.__extended = _options.extended||'js-extended';\n        this.__disabled = _options.disabled||'js-disabled';\n        this.__doRangeCheck(_options.range);\n        this.__doDateListCheck(_options.list);\n        this._$setDate(_options.date||(new Date()));\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/calendar/calendar._$$Calendar#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__list;\n        delete this.__range;\n        delete this.__nyear;\n        delete this.__nmonth;\n    };\n    /**\n     * 可选范围检测\n     * \n     * @protected\n     * @method module:util/calendar/calendar._$$Calendar#__doRangeCheck\n     * @param  {Array} arg0 - 可选择范围\n     * @return {Void}\n     */\n    _pro.__doRangeCheck = function(_range){\n        this.__range = _range||[];\n        var _value = this.__range[0];\n        this.__range[0] = _u._$isDate(_value)?(+_value):(_value||0);\n        var _value = this.__range[1];\n        this.__range[1] = _u._$isDate(_value)?(+_value):(_value||0);\n    };\n    /**\n     * 检查日期列表\n     * \n     * @protected\n     * @method module:util/calendar/calendar._$$Calendar#__doDateListCheck\n     * @param  {Array} arg0 - 日期显示列表\n     * @return {Void}\n     */\n    _pro.__doDateListCheck = (function(){\n        var _doCheck = function(_node){\n            this.__list.push(_node);\n            this.__doInitDomEvent([[\n                _node,'click',\n                this.__onDateChange._$bind(this)\n            ]]);\n        };\n        return function(_list){\n            this.__list = [];\n            _u._$forEach(_list,_doCheck,this);\n        };\n    })();\n    /**\n     * 保存日期信息\n     * \n     * @protected\n     * @method module:util/calendar/calendar._$$Calendar#__doSaveDateInfo\n     * @param  {Node}   arg0 - 节点\n     * @param  {Number} arg1 - 年份\n     * @param  {Number} arg2 - 月份\n     * @param  {Number} arg3 - 日期\n     * @return {Void}\n     */\n    _pro.__doSaveDateInfo = (function(){\n        var _isDisabled = function(_range,_time){\n            var _min = _range[0],\n                _max = _range[1];\n            return _time<_min||(!!_max&&_time>_max);\n        };\n        return function(_node,_year,_month,_date){\n            _e._$dataset(_node,'y',_year);\n            _e._$dataset(_node,'m',_month);\n            _e._$dataset(_node,'d',_date);\n            _node.innerText = _date;\n            _node.title = _year+'年'+_month+'月'+_date+'日';\n            if (_year==this.__year&&\n                _month==this.__month&&\n                _date==this.__date){\n                _e._$addClassName(_node,this.__selected);\n            }else{\n                _e._$delClassName(_node,this.__selected);\n            }\n            _isDisabled(this.__range,+new Date(_year,_month-1,_date))\n                ? _e._$addClassName(_node,this.__disabled)\n                : _e._$delClassName(_node,this.__disabled);\n        };\n    })();\n    /**\n     * 同步日历显示\n     * \n     * @protected\n     * @method module:util/calendar/calendar._$$Calendar#__doSyncDateShow\n     * @return {Void}\n     */\n    _pro.__doSyncDateShow = (function(){\n        var _days = [31,28,31,30,31,30,31,31,30,31,30,31];\n        var _isLeap = function(_year){\n            return !(_year%400)||!(_year%4)&&!!(_year%100);\n        };\n        var _getMonthDay = function(_year,_month){\n            return _month==2&&_isLeap(_year)?29:_days[_month-1];\n        };\n        return function(){\n            var _year  = this.__year,\n                _month = this.__month,\n                _date  = new Date(_year,_month-1,1),\n                _beg = ((7+_date.getDay())-this.__offset)%7,\n                _end = Math.min(\n                    this.__list.length,\n                    _beg+_getMonthDay(_year,_month)\n                );\n            // sync year and month\n            if (!!this.__nyear){\n                this.__nyear.innerText = this.__year;\n            }\n            if (!!this.__nmonth){\n                this.__nmonth.innerText = this.__month;\n            }\n            // offset with limit\n            // current month\n            for(var i=_beg,_node;i<_end;i++){\n                _node = this.__list[i];\n                this.__doSaveDateInfo(\n                    _node,_year,_month,i-_beg+1\n                );\n                _e._$delClassName(_node,this.__extended);\n            }\n            // 0 -> begin\n            // last month\n            if (_beg>0){\n                var _date = new Date(_year,_month-2||0,1);\n                var _yearTemp  = _date.getFullYear();\n                var _monthTemp = _date.getMonth()+1;\n                var _limit = _getMonthDay(_yearTemp,_monthTemp);\n                for(var i=_beg-1,_node;i>=0;i--){\n                    _node = this.__list[i];\n                    this.__doSaveDateInfo(\n                        _node,_yearTemp,_monthTemp,_limit--\n                    );\n                    _e._$addClassName(_node,this.__extended);\n                }\n            }\n            // end -> length\n            // next moth\n            var _length = this.__list.length;\n            if (_end<_length-1){\n                var _date = new Date(_year,_month,1);\n                var _yearTemp  = _date.getFullYear();\n                var _monthTemp = _date.getMonth()+1;\n                for(var i=_end,k=1;i<_length;i++){\n                    _node = this.__list[i];\n                    this.__doSaveDateInfo(\n                        _node,_yearTemp,_monthTemp,k++\n                    );\n                    _e._$addClassName(_node,this.__extended);\n                }\n            }\n        };\n    })();\n    /**\n     * 调整年份\n     * \n     * @protected\n     * @method module:util/calendar/calendar._$$Calendar#__onYearChange\n     * @param  {Number} arg0 - 步进\n     * @return {Void}\n     */\n    _pro.__onYearChange = function(_flag){\n        this.__year += _flag;\n        this.__doSyncDateShow();\n        this._$dispatchEvent('onchange',this._$getDate());\n    };\n    /**\n     * 调整月份\n     * \n     * @protected\n     * @method module:util/calendar/calendar._$$Calendar#__onMonthChange\n     * @param  {Number} arg0 - 步进\n     * @return {Void}\n     */\n    _pro.__onMonthChange = function(_flag){\n        this.__month += _flag;\n        if (this.__month<1){\n            this.__year--;\n            this.__month += 12;\n        }\n        if (this.__month>12){\n            this.__year += Math.floor(this.__month/12);\n            this.__month = (this.__month-1)%12+1;\n        }\n        this.__doSyncDateShow();\n        this._$dispatchEvent('onchange',this._$getDate());\n    };\n    /**\n     * 日期选择触发事件\n     * \n     * @protected\n     * @method module:util/calendar/calendar._$$Calendar#__onDateChange\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onDateChange = function(_event){\n        var _element = _v._$getElement(_event);\n        if (_e._$hasClassName(\n            _element,this.__disabled))\n            return;\n        this.__year  = parseInt(_e._$dataset(_element,'y'));\n        this.__month = parseInt(_e._$dataset(_element,'m'));\n        this.__date  = parseInt(_e._$dataset(_element,'d'));\n        this.__doSyncDateShow();\n        this._$dispatchEvent('onselect',this._$getDate());\n    };\n    /**\n     * 周变化触发事件\n     * \n     * @protected\n     * @method module:util/calendar/calendar._$$Calendar#__onWeekChange\n     * @param  {Number} arg0 - 上下周标识\n     * @return {Void}\n     */\n    _pro.__onWeekChange = function(_flag){\n        // TODO something\n    };\n    /**\n     * 日变化触发事件\n     * \n     * @protected\n     * @method module:util/calendar/calendar._$$Calendar#__onDayChange\n     * @param  {Number} arg0 - 上下日标识\n     * @return {Void}\n     */\n    _pro.__onDayChange = function(_flag){\n        // TODO something\n    };\n    /**\n     * 设置日期\n     *\n     * 脚本举例\n     * ```javascript\n     * _calendar._$setDate('1998-09-28');\n     * ```\n     * \n     * @method module:util/calendar/calendar._$$Calendar#_$setDate\n     * @param  {String|Number|Date} arg0 - 日期\n     * @return {Void}\n     */\n    _pro._$setDate = function(_date){\n        _date = _u._$var2date(_date);\n        this.__year  = _date.getFullYear();\n        this.__month = _date.getMonth()+1;\n        this.__date  = _date.getDate();\n        this.__doSyncDateShow();\n    };\n    /**\n     * 取当前选择时间\n     *\n     * 脚本举例\n     * ```javascript\n     * _calendar._$getDate();\n     * ```\n     * \n     * @method module:util/calendar/calendar._$$Calendar#_$getDate\n     * @return {Date} 当前选择时间\n     */\n    _pro._$getDate = function(){\n        return new Date(this.__year,this.__month-1,this.__date);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/chain/NodeList.js",
    "content": "/*\n * ------------------------------------------\n * _$$NodeList， * @version  0.1\n * @author hzzhenghaibo\n * ------------------------------------------\n */\nNEJ.define([\n    'base/event',\n    'base/element',\n    'base/util',\n    'base/chain',\n    'util/query/query'\n],function(_v,_e,_u,_x,_t){\n    var fragmentRE = /^\\s*<(\\w+|!)[^>]*>/,\n        // local vals\n        _slice = [].slice,\n        _doc = document,\n        _de = \"documentElement\",\n        _docElem = _doc[_de],\n        _testNode = _doc.createElement('div'),\n\n        // assert\n        _textHandle = _testNode.textContent == null? 'innerText' : 'textContent' ,\n        _extend = function(_name, _value, _options) {\n            _options = _options || {};\n            if (this[_name] == null || _options.override) this[_name] = _value;\n            return this;\n        },\n        _bubbleUp = function(_sl, _node, _container) {\n            while (_node && _node !== _container) {\n                if (nes.matches(_node, _sl)){\n                    return _node;\n                }\n                _node = _node.parentNode;\n            }\n        },\n        /**\n         * 根据返回类型决定返回this，还是别的什么\n         * @param  {Mix} _result\n         * @param  {String} _methodName 当前方法名\n         * @return {Mix}\n         */\n        _ischainableRet = function(_result, _methodName, _node){\n            return (_result === _node || _result === \"undefined\" || _result === this ||\n                    _result === _e || _result === _v);// 这两个是为了兼容nej\n        },\n        _isAcceptedNode = function(_node){\n            if(!_node) return false;\n            var _type = _node.nodeType;\n            return _type === 1 || _type === 9 || //  element document\n                _type === 11|| _node.window === _node; // framement window\n        },\n        // 安全的添加原型, 本作用域内\n        _safeProtoExtend = function(Type){\n            var _proto = Type.prototype,\n                _list = {};\n            return {\n                extend:function(_name, _fn){\n                    _list[_name] = _proto[_name];//先保存之前的\n                    _proto[_name] = _fn;\n                    return this;\n                },\n                reset: function(){\n                    for(var _i in _list) if(_list.hasOwnProperty(_i)){\n                        if(_list[_i] === undefined){\n                            delete _proto[_i];\n                        }else{\n                            _proto[_i] = _list[_i];\n                        }\n                    }\n                }\n            };\n        },\n        _fn = _safeProtoExtend(Function);\n\n    // 安全扩展函数原型\n    // 1. autoSet, 自动转换set({name:value})为多重set(name, value)\n    _fn.extend(\"autoSet\", function(){\n        var _fn = this;\n        return function(_key, _value) {\n            if (_u._$isObject(_key)){\n                var _args = _slice.call(arguments, 1);\n                for(var _i in _key){\n                    _fn.apply(this, [_i, _key[_i]].concat(_args));\n                }\n                return this;\n            }else{\n                return _fn.apply(this, arguments);\n            }\n        };\n    // 2. splitProcess, 自动在首参数为数组时，拆分为多步，\n    }).extend(\"splitProcess\", function(_isGetter){\n        var _fn = this;\n        return function(_params){\n            if(_u._$isArray(_params)){\n                var _args = _slice.call(arguments, 1),\n                    _len = _params.length,\n                    _ret;\n                if(_isGetter) _ret = {}; //当时getter函数需要返回值\n                for(var _i = 0 ; _i < _len ;_i++){\n                    var _param = _params[_i],\n                        _tmpRet = _fn.apply(this, [_param].concat(_args));\n                    if(_isGetter && typeof _param === \"string\") _ret[_param] = _tmpRet;\n                }\n                return _isGetter? _ret : this;\n            }else{\n                return _fn.apply(this, arguments);\n            }\n        };\n    });\n\n    _extend = _extend.autoSet();\n\n  /**\n    *    将输入的选择器指定节点或节点和节点数组包装成_$$NodeList对象，NodeList是一个类似jQuery的对象\n    *    可以进行链式操作，拥有大部分nej.e下的接口，并扩展了一部分jQuery的常用方法。\n    *\n    *    一个脑残的例子告诉你链式调用可以做什么\n    *    ```javascript\n    *    // 获得某个节点集, 设置样式\n    *    $(\"#chainable li:nth-child(odd)\")._$style({\n    *        \"background\": \"#cca\",\n    *        \"cursor\": \"pointer\"\n    *    })\n    *    // 然后抛弃他们 找他们的下一个位置条件满足是4倍数的兄弟节点并设置样式\n    *    ._$next(\":nth-child(2n)\")._$style({\n    *        \"background\": \"#a19\",\n    *        \"cursor\": \"help\"\n    *    })\n    *    // 过滤出其中是4倍数的行,并绑定事件\n    *    ._$filter(\":nth-child(4n)\")._$click(function(_e) {\n    *        $(this)._$style(\"background\", \"#111\");\n    *    // 并给他们中的第一行设置边框\n    *    })._$get(1, true)._$style(\"border\", \"3px solid #222\")\n    *    // 找到父节点div并且有chainable的id并且设置样式\n    *    ._$parent(\"div#chainable\")._$style({\n    *        width: \"800px\",\n    *        left: \"300px\",\n    *        position:\"absolute\"\n    *    // 绑定事件以及代理事件\n    *    })._$on({\n    *        \"click\" :function(){\n    *            var div = document.createElement(\"div\")\n    *            div.innerHTML = \"haha插入一行\"\n    *            //每次点击插入一行\n    *            $(this)._$insert(div, \"bottom\");\n    *        },\n    *        \"mouseover li:nth-child(odd)\":function(_e){\n    *            this._isLight = !this._isLight;\n    *            // 每次点击改变背景色\n    *            $(this)._$style(\"background-color\", this._isLight? \"#cca\":\"#331\")\n    *        }\n    *    // 获得样式值\n    *    })._$style([\"width\", \"left\"])\n    *    // 到这里链式结束返回{\"width\":\"80px\", \"left\":\"30px\"}\n    *    ```\n    *\n    *    nej.$ 支持的选择器与nes选择器一致，具体请参考 https://github.com/leeluolee/nes\n    * \n    *    结构举例\n    *    ```html\n    *      <ul>\n    *          <li><a href=\"\"></a></li>\n    *          <li><a href=\"\"></a></li>\n    *          <li><a href=\"\"></a></li>\n    *          <li><a href=\"\"></a></li>\n    *      </ul>\n    *    ```\n    * \n    *    ```javascript\n    *      var $ = NEJ.P('nej.$');\n    *      $('ul > li:nth-child(2n+1) >a')\n    *       .addClassName('odd')\n    *       ._$on('click', _callback) //将所有的奇数li节点下的a标签加上className，并进行事件绑定\n    *    ```\n    *\n    *    $接受的参数与jQuery的一致 ，非常灵活\n    *    ```javascript\n    *    // 获得\"body\"节点， 很明显此时节点集只有一个元素\n    *    $(\"body\")\n    *\n    *    // 找到有class1并且有rel属性的节点集，这时可能会有很多个节点\n    *    $(\"body li.class1[rel]\")\n    *    // 会过滤出childNodes的节点，其他Array Like也是类似\n    *    $(document.body.childNodes)\n    *\n    *    // 有时候你不确定输入的是什么参数， 安全的再包一次吧，无副作用\n    *    $body = $(\"body\")\n    *    $body2 = $($body2)\n    *    ```\n    * \n    *    @method CHAINABLE.$\n    *    @param  {String|Array|_$$NodeList|Node} _selector 可以是选择器、节点、节点数组或另一个_$$NodeList实例\n    *    @param  {String|Node|_$$NodeList} _context  代表从这个根节点下查找节点，特别是页面上节点还不存在时，需要传入这个参数\n    *    @return {_$$NodeList}           返回_$$NodeList实例\n    */\n    var $ = function(_selector, _context){\n        \n        // dump nej methods implement\n        $._$implement(_x._$dump(), {\"statics\": true});\n        _x._$clear();\n        \n        if (typeof _selector === 'string' && _selector.trim().indexOf(\"<\") == 0) {\n        var container = document.createElement('div');\n            container.innerHTML = _selector;\n            var res = $(container.childNodes);\n            return res;\n        }\n        return new _$$NodeList(_selector, _context);\n    };\n\n    function _$$NodeList(_selector, _context){\n        this.length = 0;\n        this._signs = {};//标示是否有了当前节点\n        this._context = _context || _doc;\n        if(!_selector) return ;\n        if(typeof _selector === \"string\"){\n            // if(/\\^<[-\\w]+/.test(_selector)) return $.fragment(_selector);\n            if(_context && _context instanceof _$$NodeList) _context = _context[0];\n            if(typeof _context == 'string') _context = $(_context)[0];\n            this._$add(_t._$all(_selector, _context));\n        }else if(_selector instanceof _$$NodeList || _isAcceptedNode(_selector) ||\n            _selector.length){ // _$$NodeList 或者 是单节点、或者是类数组(如childNodes)\n            this._$add(_selector);\n        }\n    }\n\n    // 扩展接口\n    $._$extend = _extend._$bind($);\n\n\n    $._$extend({\n        _$signal: \"_uid\",//会绑定在节点上的唯一标示\n        _$instances:{},// 缓存对象\n        _$handlers:[], // 保存原始handler方法\n        _$fragment: function(){\n        },\n        /**\n         * 扩展链式化接口，你可以通过两种方式，一是迁移已有的静态接口(比如NEJ的大部分接口都是这样迁移过来的)，而是直接进行_$$NodeList的原型扩展\n         *\n         * Example:\n         * ```javascript\n         * // 1. 直接扩展\n         * $._$implement(\"_$hello\", function(){\n         *     // 遍历容器内的所有节点\n         *     this._$forEach(function(_node, _index){\n         *         _node.hello = \"Hello World\"\n         *     })\n         * })\n         * $(\"li:nth-child(2n)\")._$hello() // 所有偶数行都被加上了 hello属性\n         * // 2. 直接利用静态方法进行扩展(常用语迁移), 上面扩展等价于\n         * $._$implement(\"_$hello\", function(_node){\n         *    _node.hello = \"Hello World\"\n         * }, {static: true})\n         * // 3. 创建jQuey的wrap 方法\n         * // 创建wrap方法\n         * $._$implement(\"_$wrap\", function(_selector){\n         *     var $content = $(_selector)\n         *     $content._$after2(this)._$insert(this);\n         * })\n         * $(\"#list\")._$wrap(document.createElement(\"div\"))\n         * ```\n         *\n         * 需要注意的是，当静态接口的迁移时，有如下约定(同时也是NEJ原接口在链式调用的表现约定)\n         * \n         * * 当返回值为: this 、 传入节点 、 nej.v 、 nej.e 、 undefined (即不返回)时, 视为setter操作,可以进行链式调用, 如上例:\n         * * 当返回值为其他类型时: 视为getter操作, 返回节点列表中 第一个元素 的返回值，这个也是jQuery的链式接口的表现\n         * \n         *\n         * @method CHAINABLE._$implement\n         * @param  {Object} _definition 要扩展的接口集合 (注意不要使用字符串作为键值)\n         * @param  {Object} _options 参数  目前只有两个选项{statics: 代表是否是静态接口迁移, override: 是否覆盖原同名方法}\n         * @return {this}\n         */\n        _$implement: function(_name, _fn, _options){\n            _options = _options || {};\n            _extend.call(_$$NodeList.prototype, _name, _options.statics? this._transport(_fn): _fn);\n        }.autoSet(),\n        _transport: function(_fn){\n            return function(){\n                // if(!this.length) throw Error(\"内部节点集为空\")\n                var _args = _slice.call(arguments);\n                _args.unshift(this[0]);\n\n                var _ret = _fn.apply(this,_args);\n                // 当返回_e、_v、this、_node、undefined(无返回值)都视为链式\n                if(!_ischainableRet.call(this, _ret)) return _ret;\n\n                this._$forEach(function(_node, _index){\n                    if(_index === 0) return;\n                    _args[0] = _node;\n                    _fn.apply(this ,_args);\n                });\n                return this;\n            };\n        },\n        _merge: function(_list1, _list2 , _filter){\n            var _i = _list1.length || 0,\n                _j = 0;\n            for( ;_list2[_j] !== undefined;){\n                var _tmp = _list2[_j++];\n                if(!_filter || _filter.call(_list1, _tmp)){\n                    _list1[_i++] = _tmp;\n                }\n            }\n            _list1.length = _i;\n            return _list1;\n        },\n        _toArray: function(_list){\n            return $._merge([], _list);\n        },\n        // ** fork form jQuery **\n        _contains: _docElem.contains ? function( _a, _b ) {\n            return _a === _b || (_a.nodeType == 9? _a[_de]: _a).contains(_b);\n        }: _docElem.compareDocumentPosition ?\n        function( _a, _b ) {\n            // more info : https://gist.github.com/4601579\n            return _b && !!( _a.compareDocumentPosition( _b ) & 16 );\n        }: function( _a, _b ) {\n            // fallback\n            while ( (_b = _b.parentNode) ) {\n                if ( _b === _a ) return true;\n            }\n            return false;\n        },\n        _$cloneNode:function(_node, _withContent){\n            _withContent = !!_withContent;\n            var _clone = _node.cloneNode(_withContent),\n                _ce, _be;\n\n            if(_withContent){\n                _be = nes.all(\"*\", _node);\n                _be.push(_node);\n                _ce = nes.all(\"*\", _clone);\n                _ce.push(_clone);\n            }else{\n                _be = [_node];\n                _ce = [_clone];\n            }\n\n            for (_i = _ce.length; _i--;){\n                _definitions.fixture.clone(_ce[_i], _be[_i]);\n            }\n            return _clone;\n        },\n        _delegateHandlers : {},// for delegate\n        _cleanSelector : nes._cleanSelector,\n        _$uniqueSort : nes._uniqueSort,\n        _$matches : nes.matches,\n        _$fn: _$$NodeList.prototype,\n        _$uid : nes._getUid\n    });\n\n    // proto function 扩展\n    // ================================\n    var _rclickEvents = /^(?:click|dblclick|contextmenu|DOMMouseScroll|mouse(?:\\w+))$/,\n        _rkeyEvents = /^key(?:)/,\n        _definitions ={\n        // for insert\n        // 这里统一视为_node2为插入点\n        \"insertor\":{\n            \"top\":function(_node, _node2){\n                _node.insertBefore(_node2, _node.firstChild);\n            },\n            \"bottom\": function(_node, _node2){\n                _node.appendChild(_node2);\n            },\n            \"before\":function(_node, _node2){\n                var _parent = _node.parentNode;\n                if(_parent) _parent.insertBefore(_node2, _node);\n            },\n            \"after\":function(_node, _node2){\n                var _parent = _node.parentNode;\n                if(_parent) _parent.insertBefore(_node2, _node.nextSibling);\n            }\n        },\n        fixProps :{\n            // 确保表单元素属性被正确设置 IE lt9\n            input: 'checked',\n            option: 'selected',\n            textarea: 'value',\n            // clone时 , IE某些版本不会正确设置text\n            script:\"text\"\n        },\n        fixture:{\n            // dest src attribute fixed\n            \"clone\": function(_dest, _src){\n                var _nodeName, _attr;\n\n                if (_dest.nodeType !== 1) {\n                    return;\n                }\n                // lt ie9 才有\n                if (_dest.clearAttributes) {\n                    _dest.clearAttributes();\n                    _dest.mergeAttributes(_src);\n                }\n                // 判断是否有需要处理属性的节点\n                _nodeName = _dest.nodeName.toLowerCase();\n                if(_prop = _definitions.fixProps[_nodeName]){\n                    _dest[_prop] = _src[_prop];\n                }\n                //移除节点标示\n                _dest.removeAttribute($._$signal);\n                // 移除ID:  TODO? 是否允许有重复ID?\n                _dest.removeAttribute(\"id\");\n            },\n            //patch event\n            \"event\":function(_e){\n                var _type = _e.type;\n                var _button = _e.button;\n                _e.__fixed = true; //标示被fix过\n                _e.target = _e.target || _e.srcElement || document; //for ie\n                _e.metaKey = !!_e.metaKey; //低版本ie会返回undefined 应该返回\n\n\n                if(_e.target.nodeType === 3) _e.target = _e.target.parentNode;\n                if(_rclickEvents.test(_type)){ //如果是鼠标事件 则初始化page相关\n                    _e.pageX = _v._$pageX(_e);\n                    _e.pageY = _v._$pageY(_e);\n                    if (_type === 'mouseover' || _type === 'mouseout'){//如果是鼠标事件中的mouseover与mouseout\n                        var related = _e.relatedTarget || _e[(_type == 'mouseover' ? 'from' : 'to') + 'Element'];\n                        while (related && related.nodeType == 3) related = related.parentNode;\n                        _e.relatedTarget = related;\n                    }\n                }\n                _e.which = _e.charCode != null ? _e.charCode : _e.keyCode;\n                if( !_e.which && _button !== undefined){\n                    // http://api.jquery.com/event.which/ use which\n                    _e.which = ( _button & 1 ? 1 : ( _button & 2 ? 3 : ( _button & 4 ? 2 : 0 ) ) );\n                }\n                if(!_e.preventDefault) _e.preventDefault = function(){\n                    this.returnValue = false;\n                    return this;\n                };\n\n                if(!_e.stopPropagation) _e.stopPropagation = function(){\n                   this.cancelBubble = true;\n                   return this;\n                };\n            }\n        }\n    },\n    // for traverse\n    _traverse = function(_direct){\n        var _$matches = $._$matches;\n\n        return function(_selector, _all){\n            var _ret = $([]);\n            if(typeof _selector === \"boolean\"){\n                _all = _selector;\n                _selector = null;\n            }\n            this._$forEach(function(_node){\n                var _tmp = _node[_direct];\n                while (_tmp) {\n                  if(_tmp.nodeType ===1 && (!_selector || _$matches(_tmp, _selector))){\n                    _ret._$add(_tmp);\n                    if(!_all) break;\n                  }\n                  _tmp = _tmp[_direct];\n                }\n            });\n            return _ret;\n        };\n    };\n\n\n    $._$implement({\n     /**\n      * 获取节点样式或者设置节点样式, 这个接口的表现与jQuery的css方法一致, 根据参数不同有不同的表现\n      * 比如:\n      * ```javascript\n      * $('li')._$style(name) //相当于_$getStyle 返回样式值\n      * $('li')._$style([name1,name2...]) //相当于多重_$getStyle 返回一个Object(如{\"height:20px, width:30px...\"})\n      * $('li')._$style(name, value) // 相当于setStyle 返回this\n      * $('li')._$style(obj) //相当于多重版setStyle(即原_$style) 返回this\n      * ```\n      * @method CHAINABLE._$style\n      * @param  {String|Object|Array} _key  可以是String(单取值或设置)，一个对象(多重赋值)，一个数组(多重取值)\n      * @param  {String} _value 样式值\n      * @return {_$$Nodelist|String|Object} setter操作返回_$$NodeList，单重取值返回String，多重取值返回样式属性为键的Object，表现与jQuery的css接口一致\n      */\n        _$style: function(_key, _value){\n            if(!_key) throw Error(\"缺少css样式名\");\n            if(_value === undefined){\n                return _e._$getStyle(this[0], _key);\n            }\n            return this._$forEach(function(_node){\n                _e._$setStyle(_node, _key, _value);\n            });\n        }.splitProcess(true).autoSet(),\n       /**\n        * 获取节点属性或者设置节点属性, 这个接口的表现与jQuery的attr一致, 同_$style接口，根据参数不同有不同的表现\n        * 比如:\n        * ```javascript\n        * $('li')._$attr(name): 相当于_$attr 返回属性值\n        * $('li')._$attr([name1, name2]) 同style描述 返回{titile:\"xxx\",rel:\"xxx\", href:\"xxx\"}\n        * $('li')._$attr(name, value): 相当于_$attr 返回this\n        * $('li')._$attr(obj): 相当于多重版的_$attr 返回this\n        * ```\n        * \n        * @method CHAINABLE._$attr\n        * @param  {String|Object|Array} _key  可以是String(单取值或设置)，一个对象(多重赋值)，一个数组(多重取值)\n        * @param  {String} _value 属性值\n        * @return {_$$Nodelist|String|Object} setter操作返回_$$NodeList，单重取值返回String，多重取值返回样式属性为键的Object，表现与jQuery的css接口一致\n        */\n        _$attr: function(_key, _value){\n            if(!_key) throw Error(\"缺少属性名\");\n            if(_value === undefined){\n                return _e._$attr(this[0], _key);\n            }\n            return this._$forEach(function(_node){\n                _e._$attr(_node, _key, _value);\n            });\n        }.splitProcess(true).autoSet(),\n\n        /**\n         * 类似于ES5的Array#forEach, 一个遍历函数, 即遍历_$$NodeList的所有节点集\n         * 比如:\n         * ```javascript\n         * // 将1,4,7...class含有strong的li元素分别加上阶梯型的高度\n         * $(\"li.strong:nth-child(3n+1)\")._$forEach(function(_node, _index){\n         *     _node.style.height = \"\" + (_index+1)*10 + \"px\";\n         *     // 这里的this指向实例\n         * })\n         * ```\n         * 注意callback中传入的节点是裸节点，而不是包装后的_$$NodeList\n         * \n         * @method CHAINABLE._$forEach\n         * @param  {Function} _fn 遍历回掉，接受两个参数，当前遍历到的节点和节点下标\n         * @return {_$$NodeList}\n         */\n        _$forEach: function(_fn){\n            _u._$forEach(this, _fn);\n            return this;\n        },\n\n      /**\n       * 类似于ES5的Array#filter, 一个过滤, 即过滤_$$NodeList的所有节点集并筛选符合的节点\n       * 比如:\n       * ```javascript\n       * // 返回节点集中的匹配选择器.strong:nth-child(3n)的节点\n       * $(\"li\")._$filter(\".strong:nth-child(3n)\")\n\n       * // 相当于  ===>\n       * $(\"li\")._$filter(function(_node){\n       *     return $(_node)._$matches(\".strong:nth-child(3n)\");\n       * });\n       * ```\n       * 注意callback中传入的节点是裸节点，而不是包装后的_$$NodeList\n       * \n       * @method CHAINABLE._$filter\n       * @param  {Function|String} _fn 遍历函数，接受两个参数，当前遍历到的节点和节点下标。同时也接受一个Selector，筛选出节点集中满足选择器的节点\n       * @return {_$$NodeList}\n      */\n        _$filter: function(_fn){\n            var _ret = [],\n                _isSelctor = typeof _fn === \"string\";\n            this._$forEach(function(_node, _index){\n                var _test = _isSelctor ? $._$matches(_node, _fn):_fn.call(this, _node, _index);\n                if(_test) _ret.push(_node);\n            });\n            return $(_ret);\n        },\n        /**\n         * 相当于ES5的Array#map, 当返回值全部是节点类型时，返回$NodeListchainable, 否则返回标准结果数组(此时chainable不能)\n         *\n         * example:\n         * ```javascript\n         * // 此时返回Array : [\"li\", \"li\", \"li\".........]\n         * $(\"li\")._$map(function(_node){\n         *     return _node.tagName.toLowerCase()\n         * });\n         * // 此时返回 $NodeList: 即所有节点的下一个兄弟节点\n         * $(\"li\")._$map(function(_node){\n         *     return _node.nextSibling\n         * });\n         * ```\n         * 注意callback中传入的节点是裸节点，而不是包装后的_$$NodeList\n         * \n         * @method CHAINABLE._$map\n         * @param  {Function} _fn 遍历callback，接受两个参数，当前遍历到的节点和节点下标\n         * @return {_$$NodeList}\n         */\n        _$map:function(_fn){\n            var _ret = [],\n                _isNotAllNode = false;\n            this._$forEach(function(_node, _index){\n                var _res = _fn.call(this, _node, _index);\n                if(!_isAcceptedNode(_res)) _isNotAllNode = true;\n                _ret.push(_res);\n            });\n            return _isNotAllNode ? _ret : $([])._$add(_ret);\n        },\n        /**\n         * NodeList中的节点是不保证按文档顺序的(如果是用选择器，则保证是有序的), 你可以手动排序\n         * \n         * @method CHAINABLE._$sort\n         * @return {_$$NodeList}\n         */\n        _$sort:function(){\n            var _array = this._$get();\n            $._$uniqueSort(_array);\n            return $(_array);\n        },\n        /**\n         * 向内部节点集填入元素, 会处理好重复以及过滤的逻辑。这个也是$接口依赖的方法。\n         * ```javascript\n         * var $body = $(\"body\")\n         * $body._$add($(\"tbody\")) //==> 添加tbody\n         * $body._$add($(\"tbody\")) //==> 什么都不会发生 因为重复了\n         * $body._$add(document.body.childNodes) //==> 添加所有的body下的子节点,过滤掉不符合的\n         * ```\n         * \n         * @method CHAINABLE._$add\n         * @param  {Node|Array|_$$NodeList} _node 要添加的节点或节点集\n         * @return {_$$NodeList}      返回this\n         */\n        _$add:function(_node){\n            if(!_node) return;\n            // TODO: 把window 排除在外\n            if(_node.tagName || typeof _node.length !== \"number\" || _node === window ) _node = [_node];\n            $._merge(this, _node, function(_nodum){\n                if(!_isAcceptedNode(_nodum)) return false;\n                var _uid = $._$uid(_nodum);\n                if(this._signs[_uid]){\n                    return false;\n                }else{\n                    this._signs[_uid] = 1;\n                    return true;\n                }\n            });\n            return this;\n        },\n        _$get:function(_index, wrap){\n            if(typeof _index !== \"number\") return $._toArray(this);\n            return wrap ? $(this[_index]) : this[_index];\n        },\n        _$last: function(wrap){\n            return wrap? $(this[this.length-1]) : this[this.length-1];\n        },\n        _$first: function(wrap){\n            return wrap? $(this[0]) : this[0];\n        },\n        /**\n         * 判断包装节点是否满足某个选择器，即Selector API的matches方法。如果节点集内不止一个节点，则只判断第一个节点\n         * Exmaple:\n         * ```javascript\n         *  $(\"body tbody td:nth-child(4n)\")._$matches(\"body tbody td:nth-child(2n)\")\n         *  //返回 true... 这个是当然的, 4倍数的节点当然满足偶数条件\n         * ```\n         *\n         * \n         * @method CHAINABLE._$matches\n         * @param  {String} _selector 供测试的选择器\n         * @return {Boolean}          是否通过测试\n         */\n        _$matches: function(_selector){\n            return $._$matches(this[0],_selector);\n        },\n        /**\n         * 查找 所有节点 的第一个(或所有)满足关系的 父节点 集, 并返回$NodeList\n         *\n         * Example:\n         * ```javascript\n         * $(\"tr\")._$parent()\n         * //=> ['tbody', 'thead'],两个是因为节点集中的tr元素可能在tbody或thead中\n         * $(\"tr\")._$parent(\"tbody\")\n         * //=> ['tbody'] 必须满足tbody\n         * $(\"tr\")._$parent(true)\n         * // =>['tbody', 'thead', 'div', 'body' ....] //会向上查找所有父节点\n         * $(\"tr\")._$parent(\"tbody, body\",true)\n         * // =>['body', 'tbody'] //会向上查找所有父节点,但是必须满足选择器\n         * ```\n         * @method CHAINABLE._$parent\n         * @param  {String} _selector 选择器\n         * @param  {Boolean} _all     是否获取所有层级的父节点\n         * @return {[type]}\n         * @type {[type]}\n         */\n        _$parent: _traverse(\"parentNode\"),\n        /**\n         * 与_$parent类似,查找 所有节点 的第一个(或所有根据_all参数)满足关系的 前序兄弟节点 (previousSibling)集, 并返回$NodeList\n         * ```javascript\n         * $(\"td\")._$prev(\"th[scope=row]\", true)\n         * // 返回所有在td之前的th元素, 它们的scope属性为 row\n         * $(\"td\")._$prev(\"th[scope=row]\")\n         * // 只返回直接相邻的前节点，如果不满足选择器则返回空节点集\n         * ```\n         * @method CHAINABLE._$prev\n         * @param  {String} _selector 选择器\n         * @param  {Boolean} _all     是否获取所有前序节点\n         * @return {[type]}\n         */\n        _$prev: _traverse(\"previousSibling\"),\n        /**\n         * 与_$prev类似,查找 所有节点 的第一个(或所有根据_all参数)满足关系的 向后兄弟节点 (nextSibling)集, 并返回$NodeList\n         * @method CHAINABLE._$next\n         * @param  {String} _selector 选择器\n         * @param  {Boolean} _all     是否获取所有后序节点\n         * @return {[type]}\n         */\n        _$next: _traverse(\"nextSibling\"),\n        /**\n         * 查找到 本节点集中 所有节点 的满足选择器关系的 直接子节点 (或 任意层级子节点 )集, 并返回$NodeList\n         * ```javascript\n         * $(\"body, table\")._$children();\n         * // => 相当于 合并body与table的直接子节点\n         * $(\"body, table\")._$children(\"div, thead\");\n         * // => 只要他们子节点中的div 与 thead元素\n         * $(\"body, table\")._$children(true);\n         * // => 这里会获取所有body下的所有层级的子节点(table也在body中)\n         * $(\"body, table\")._$children(\"td:not(:last-child, :nth-child(2n))\",true);\n         * // => 返回所有层级的td元素并且满足选择器 td:not(:last-child, :nth-child(2n))\n         * ```\n         *\n         * @method CHAINABLE._$children\n         * @param  {String} _selector 选择器\n         * @param  {Boolean} _all     是否获取所有层级的节点\n         * @return {[type]}\n         */\n        _$children: function(_selector, _all){\n            var _ret = $([]);\n            if(typeof _selector === \"boolean\"){\n                _all = _selector;\n                _selector = null;\n            }\n            this._$forEach(function(_node){\n                var _backed = _all? _t._$all(_selector || \"*\", _node)\n                    : _selector? $(_node.childNodes)._$filter(_selector)\n                    : $(_node.childNodes);\n                _ret._$add(_backed);\n            });\n            return _ret;\n        },\n        /**\n         * 满足选择器条件的同级节点，但不包含本身\n         * Example\n         * ```javascript\n         * $(\"script\")._$siblings(\"title,h2\"); // => 返回script的同级节点中的\n         * ```\n         *\n         * \n         * @method CHAINABLE._$siblings\n         * @param  {String} _selector\n         * @return {_$$NodeList}    这些同级节点会被包装为一个_$$NodeList\n         */\n        _$siblings: function(_selector){ // sibling 默认就是取所有\n            return this._$prev(_selector, true)._$add(this._$next(_selector, true));\n        },\n        /**\n         * 这个insert 拥有jQuery的四个接口的功能(before, after, prepend , append) ，分别用_direct参数控制\n         *\n         * Example:\n         * ```javascript\n         * //将`a.next`插到`#home`的内部的最上方\n         * $('#home')._$insert('a.next', 'up');\n         * //将a.next插入到`#home`节点后面\n         * $('#home')._$insert('a.next', 'after');\n         * ```\n         *\n         * @method CHAINABLE._$insert\n         * @param  {String|Node|_$$NodeList} _selector 代表被插入的节点，可以是选择器、节点或是另外一个_$$NodeList对象\n         * @param  {String} _direct   插入位置，可以是节点内的底部、顶部(bottom, top)，或节点同层的前后位置(before, after)，默认为bottom\n         * @return {_$$NodeList}    返回this\n         */\n        _$insert: function(_selector, _direct){\n            _direct = (_direct && _direct.toLowerCase()) || \"bottom\";\n            if(!_definitions.insertor[_direct]) _direct = \"bottom\";\n            var _content = $(_selector)[0], //将被插入的节点\n                _insertor = _definitions.insertor[_direct];\n            if(!_content) throw Error(\"The Element to be inserted is not exist\");\n\n            return this._$forEach(function(_node, _index){\n                _insertor(_node, _index === 0? _content\n                    : $._$cloneNode(_content, true));//如果是多个节点则cloneNode\n            });\n        },\n        /**\n         * 这个_$insert2 拥有jQuery的四个接口的功能(insertBefore, insertAfter, prependTo , appendTo) ，分别用_direct参数控制。其实就是_$insert接口的相反版，\n         * 你做的是将被插入节点插入到某个节点的指定位置。\n         *\n         * Example:\n         * ```javascript\n         * //将`#home`插到`a.next`的内部的最上方\n         * $('#home')._$insert2('a.next', 'up');\n         * //将`#home`插入到`a.next`节点后面\n         * $('#home')._$insert2('a.next', 'after');\n         * ```\n         *\n         * @method CHAINABLE._$insert2\n         * @param  {String|Node|_$$NodeList} _selector 代表参考节点，可以是选择器、节点或是另外一个_$$NodeList对象\n         * @param  {String} _direct   插入位置，可以是节点内的底部、顶部(bottom, top)，或节点同层的前后位置(before, after)，默认为bottom\n         * @return {_$$NodeList}    返回this\n         */\n        _$insert2: function(_selector, _direct){\n            $(_selector)._$insert(this, _direct);\n            return this;\n        },\n        /**\n         * 克隆节点集内部的 所有节点, 并返回clone的目标节点集 $NodeList 实例\n         *\n         * Example:\n         * ```javascript\n         * $('.m-template')._$clone(true)._$insert2('body');//将`.m-template`节点clone一份插入到`body`的内部下方\n         * ```\n         *\n         * @method CHAINABLE._$clone\n         * @param  {Boolean} _withContent 是否要克隆子节点\n         * @return {_$$NodeList}\n         */\n        _$clone: function(_withContent){\n            return this._$map(function(_node){\n                return $._$cloneNode(_node, _withContent);\n            });\n        },\n        /**\n         * 获得节点集中的 第一个元素的innerText 或者 设置所有元素的innerText\n         *\n         * Example:\n         * ```javascript\n         * $(\"title,h2\")._$text(\"haha\")\n         * // 同时设置title与h2的text内容为haha\n         * $(\"title,h2\")._$text()\n         * // 获得title(第一个元素)的innerText\n         * ```\n         *\n         * \n         * @method CHAINABLE._$text\n         * @param  {content} _content 要插入的内容 , 不传入则认为是getter操作\n         * @return {_$$NodeList|String} setter操作返回_$$NodeList getter操作返回String\n         */\n        _$text: function(_content){\n            if(_content === undefined){\n                if(!this[0]) throw Error(\"内部节点为空，无法完成get操作\");\n                return this[0][_textHandle];\n            }\n            return this._$forEach(function(_node){\n                _node[_textHandle] = _content;\n            });\n        },\n        /**\n         * 获得节点集中的 第一个元素的innerHTML 或者设置所有元素的innerHTML(与_$text接口类似)\n         *\n         * Example:\n         * ```javascript\n         * $(\"title,h2\")._$html(\"haha\")\n         * // 同时设置title与h2的innerHTML为haha\n         * $(\"title,h2\")._$html()\n         * // 获得title(第一个元素)的innerHTML\n         * ```\n         *\n         * \n         * @method CHAINABLE._$html\n         * @param  {content} _content 要插入的内容 不传入则认为是getter操作\n         * @return {_$$NodeList|String} setter操作返回_$$NodeList getter操作返回String\n         */\n        _$html: function(_content){\n            if(_content === undefined){\n                if(!this[0]) throw Error(\"内部节点为空，无法完成get操作\");\n                return this[0].innerHTML;\n            }\n            return this._$forEach(function(_node){\n                _node.innerHTML = _content;\n            });\n            return this;\n        },\n        /**\n         * 获得节点集中的 第一个元素的value 或者设置所有元素的value(与_$text接口类似)\n         *\n         * Example:\n         * ```javascript\n         * $(\"input,textarea\")._$val()\n         * // 获取第一个满足'input,textarea'选择器元素的value值\n         * $(\"title,h2\")._$html(\"haha\")\n         * // 获得title(第一个元素)的innerHTML\n         * ```\n         *\n         * \n         * @method CHAINABLE._$html\n         * @param  {content} _content 要插入的内容\n         * @return {_$$NodeList|String} setter操作返回_$$NodeList getter操作返回String\n         */\n        _$val:function(_content){\n            if(_content === undefined){\n                if(!this[0]) throw Error(\"内部节点为空，无法完成get操作\");\n                return this[0].value;\n            }\n            return this._$forEach(function(_node){\n                _node.value = _content;\n            });\n            return this;\n        },\n\n        // 事件相关\n        // ==============\n        // 私有方法  注册事件代理\n        _delegate:function(_event, _selector, _handler){\n            _selector = $._cleanSelector(_selector);\n            return this._$forEach(function(_node){\n                var _uid = $._$uid(_node),\n                    _handlers = $._delegateHandlers[_uid] || ($._delegateHandlers[_uid] = {}),\n                    _events = _handlers[_event] || (_handlers[_event] = {}),\n                    _selectors = _events[_selector] || (_events[_selector] = []);\n\n                var _realCb = function(_e) {//正式回调\n                    var _trigger;\n                    if (_trigger = _bubbleUp(_selector, _e.target || _e.srcElement , _node)) {\n                        _handler.apply(_trigger, arguments);\n                    }\n                };\n                // 保存引用 以可以正确off\n                _realCb._raw = _handler;\n                _selectors.push(_realCb);\n                // 假如不存在对应的容器，则先创建\n                _v._$addEvent(_node, _event, _realCb);\n                // Fix: 我们保存原始_handler为了 nej的 delEvent可以正确解绑\n                // 省去再存储一份handler列表的开销\n            });\n        },\n        // 私有方法 解绑事件代理\n        _undelegate:function(_event, _selector, _handler){\n            _selector = $._cleanSelector(_selector);\n            return this._$forEach(function(_node){\n                var _uid = $._$uid(_node);\n                var _handlers, _events, _selectors;\n                if (!(_handlers = $._delegateHandlers[_uid]) ||\n                    !(_events = _handlers[_event]) || !(_selectors = _events[_selector])){\n                    return;\n                }\n                for(var _len = _selectors.length;_len--;){\n                    var _fn = _selectors[_len];\n                    //如果没有传入_handler或者 函数匹配了\n                    if(!_handler || _fn._raw === _handler){\n                        _v._$delEvent(_node, _event, _fn);\n                        _selectors.splice(_len,1);\n                    }\n                }\n                // 如果被删光了\n                if(!_selectors.length) delete _events[_selector];\n            });\n            return this;\n        },\n        /**\n         * 绑定事件，可以使用事件代理, 与jQuery的on类似\n         *\n         * __Example:__\n         * ```javascript\n         * // 1. 普通事件绑定\n         * $(\"body\")._$on(\"click\", function(_e){\n         *     alert(\"单个事件绑定\"+_e.type)\n         * })\n         * // 2. 多个普通类型绑定到同一个handler\n         * $(\"body\")._$on([\"click\", \"mouseover\"], function(_e){\n         *     alert(\"多个type绑定\"+_e.type)\n         * })\n         * // 3. 单个代理事件绑定 这里等同于_$on(\"click\", \"tr:nth-child(2n)\", handler)\n         * $(\"body\")._$on(\"click tr:nth-child(2n)\", function(_e){\n         *     // this 对象指向当前`触发`事件的tr:nth-child(2n)\n         *     _e.preventDefault()\n         *     alert(\"单个代理事件绑定\"+_e.type)\n         * })\n         * // 4. 多个事件绑定(同回调), 这里分别是普通事件dblclick与代理事件click tr:nth-child(2n)\n         * $(\"body\")._$on([\"dblclick\", \"click tr:nth-child(2n)\"], function(_e){\n         *     _e.preventDefault()\n         *     alert(\"多个事件类型绑定\"+_e.type)\n         * })\n         * // 5. 多重事件绑定,\n         * $(\"body\")._$on({\n         *     \"dblclick\":function(_e){\n         *         alert(\"多重事件绑定之普通版\"+_e.type)\n         *     },\n         *     \"click tr:nth-child(2n)\":function(_e){\n         *         alert(\"多重事件绑定之代理版\"+_e.type)\n         *     }\n         * })\n         * ```\n         * \n         * @method CHAINABLE._$on\n         * @param  {String|Array|Object} _event     事件名，_event支持多种参数类型会有不同的结果\n         *                             如果_event参数中不包含空格, 则视为简单事件绑定如，click,\n         *                             如果_event参数中包含空格,则会被split, 左边视为event参数，右边视为_selector参数如'click .next',\n         *                             如果_event是个Ojbect,则会视为多重绑定,如{'click .next': callback1, 'mouseover': callback2}\n         *                             如果_event是个Array, 则会对多个_event进行同一个函数的绑定, 如['click','mouseover']\n         * @param  {String} _selector  如果传入则代表是一个事件代理,可忽略\n         * @param  {Function} _handler 回掉函数\n         * @return {_$$NodeList}\n         */\n        _$on:function(_event, _selector, _handler){\n            if(_event === undefined) throw Error(\"缺少事件名参数\");\n            if(typeof _selector === \"function\"){\n                _handler = _selector;\n                _selector = null;\n            };\n            var _index = _event.indexOf(\" \");\n            if(~_index){//有空格分隔 如\"click div.m-model\"\n                _selector = _event.slice(_index + 1);\n                _event = _event.slice(0, _index);\n            }\n            if(!_handler) throw Error(\"缺少回调函数\");\n            // 创建一个realHandler\n            else {\n                var _raw = _handler;\n                var _handler = function(_e){\n                    _definitions.fixture.event(_e);\n                    _raw.apply(this, arguments);\n                };\n                _raw.real = _handler;//\n            }\n            if(_selector){ // on (\"click\", \"li.clas1\", handler)或 on(\"click\", \"li.class1\")\n                return this._delegate(_event,_selector, _handler);\n            }\n            // on(\"click\", handler)\n            return this._$forEach(function(_node){\n                _v._$addEvent(_node, _event, _handler);\n            });\n        }.splitProcess().autoSet(),\n\n        /**\n         * 为 节点集内的每一个节点 解除事件回调, 类似jQuery的off方法\n         * __Example__\n         * ```javascript\n         * // 1. 普通事件解绑\n         * $(\"body\")._$off(\"click\", handler)\n         * // 2. 多个普通类型事件解绑(同一个handler)\n         * $(\"body\")._$off([\"click\", \"mouseover\"], handler)\n         * // 3. 普通事件清除(即不传入handler) __同时会把节点上click类型的代理事件清除!__\n         * $(\"body\")._$off(\"click\")\n         * // 4. 多个普通事件清除 同时会把节点上相应类型的代理事件清除!\n         * $(\"body\")._$off([\"click\",\"mouseover\"])\n         * // 5. 单个代理事件的解绑\n         * $(\"body\")._$off(\"click\",\"tr:nth-child(2n)\", handler)\n         * // 或\n         * $(\"body\")._$off(\"click tr:nth-child(2n)\", handler)\n         * // 6. 多个代理事件的解绑(同一个handler)\n         * $(\"body\")._$off([\"dblclick td[title]\", \"click tr:nth-child(2n)\"], handler)\n         * // 7. 代理事件的清除\n         * $(\"body\")._$off(\"dblclick\",\"td[title]\");\n         * $(\"body\")._$off(\"dblclick td[title]\");\n         * $(\"body\")._$off([\"dblclick td[title]\", \"click tr:nth-child(2n)\"])\n         * // 8. 多重事件解绑\n         * $(\"body\")._$off({\n         *     \"dblclick td\":handler1,\n         *     \"click tr\":handler2\n         * });\n         * // 9. 所有事件清除\n         * $(\"body\")._$off() //慎重\n         * ```\n         *\n         * \n         * @method CHAINABLE._$off\n         * @param  {String|Array|Object} _event 与_$on方法一样，解绑也会根据参数不同可以有很大的灵活度\n         *                                      如果_event参数中不包含空格, 则视为简单事件解绑如，click,\n         *                                      如果_event参数中包含空格,则会被split, 左边视为event参数，右边视为_selector参数如'click .next',\n         *                                      如果_event是个Ojbect,则会视为多重解绑, 如{'click .next': callback1, 'mouseover': callback2}\n         *                                      如果_event是个Array, 则会对多个_event进行同一个函数的解绑, 如['click','mouseover']\n         *                                      需要注意_$off与_$on不同的是_event也可以是个空值，代表会解决节点下的所有事件\n         * @param  {[type]} _selector [description] 如果传入_selector参数，则会进行事件代理的事件解绑, 可忽略\n         * @param  {[type]} _handler  [description] 要解绑对应回调，可忽略\n         * @return {_$$NodeList}\n         */\n        _$off:function(_event, _selector, _handler){\n            if(typeof _selector === \"function\"){\n                _handler = _selector;\n                _selector = null;\n            }\n            var _index;\n            if(_event && ~(_index = _event.indexOf(\" \"))){//有空格分隔 如\"click hello\"\n                _selector = _event.slice(_index + 1);\n                _event = _event.slice(0, _index);\n            }\n            if(_handler) _handler = _handler.real || _handler;\n            if(_selector){ // off(\"click\", \".class\")   off(\"click\", \".class\", handler)\n                return this._undelegate(_event, _selector, _handler);\n            }\n            return this._$forEach(function(_node){\n                var _uid = $._$uid(_node),\n                    _handlers = $._delegateHandlers[_uid],\n                    _events;\n                if(!_event){ // off()\n                    if(_handlers){\n                        delete $._delegateHandlers[_uid]; // 删除所有\n                    }\n                    _v._$clearEvent(_node, _event);\n                }else{\n                    if(_handlers) _events = _handlers[_event];\n                    if(!_handler){ // off(\"click\")\n                        if(_events){\n                            delete _handlers[_event];\n                        }\n                        _v._$clearEvent(_node, _event);\n                    }else{ // off(\"click\", handler)\n                        // 这里不对delegate做清理是因为 这样不会对delegate发生影响\n                        _v._$delEvent(_node, _event, _handler);\n                    }\n                }\n            });\n        }.splitProcess().autoSet(),\n        /**\n         * 触发每个节点的对应事件, 同nej.v._$dispatchEvent，区别是参数类型自由度高一点\n         *                                      如果_event参数为String, 则视为简单事件触发如，click,\n         *                                      如果_event是个Ojbect,则会视为多重触发, 如{'click': param1, 'mouseover': param2}\n         *                                      如果_event是个Array, 则会对多个_event进行触发(公用一个options), 如['click','mouseover']\n         * Example:\n         * ```javascript\n         * //触发一个事件\n         * _$trigger(\"click\", params)\n         * //一次触发多个事件(如果有参数，他们共用这个参数)\n         * _$trigger([\"click\", \"mouseover\"], params)\n         * // 触发多个事件有不同参数\n         * _$trigger({\n         *     \"click\": params1,\n         *     \"dblclick\": params2\n         * })\n         * ```\n         *\n         * @method CHAINABLE._$trigger\n         * @param  {String|Array|Object} _event   可以传入多种参数类型\n         * @param  {Whatever} _options 同_$dispatchEvent的_options\n         * @return {_$$NodeList}\n         */\n        _$trigger:function(_event, _options){\n            if(typeof _event !== 'string') throw Error(\"事件类型参数错误\");\n            this._$forEach(function(_node){\n                _v._$dispatchEvent(_node, _event, _options);\n            });\n            return this;\n        }.splitProcess().autoSet(),\n\n        // http://stackoverflow.com/questions/6599071/array-like-objects-in-javascript\n        // 让这个对象看起来像数组\n        splice: function(){ throw Error(\"don't use the NodeList#splice\");}\n    });\n    // @ remove 无法被混淆的方法\n    // // 无奈 添加 _$before // _$before2   _$bottom _$bottom2等方法\n    // _u._$forIn(_definitions.insertor, function(_value, _key){\n    //     $._$implement(\"_$\" + _key, function(){\n    //        var _args = _slice.call(arguments);\n    //        _args.push(_key)\n    //        return this._$insert.apply(this, _args)\n    //     })\n    //     $._$implement(\"_$\" + _key+\"2\", function(){\n    //        var _args = _slice.call(arguments);\n    //        _args.push(_key)\n    //        return this._$insert2.apply(this, _args)\n    //     })\n    // })\n\n    // // 添加类似 _$click的事件\n    // // ================================\n    // // TODO: 检查是否有遗漏的方法\n    //    @\n    // var _beAttached = \"click dbclick blur change focus focusin focusout keydown keypress keyup mousedown mouseover mouseup mousemove mouseout scroll select submit\".split(\" \");\n\n    // @ remove 无法被混淆 移除\n    // _u._$forEach(_beAttached, function(_eventName){\n    //     $._$implement(\"_$\"+_eventName, function(){\n    //         var _type = typeof arguments[0];\n    //         var _args = _slice.call(arguments);\n    //         _args.unshift(_eventName);\n    //         // click(\"li\", handler)   或者  click(handler)\n    //         if((_type == \"function\") || (_type === \"string\" && typeof arguments[1] === \"function\")){\n    //             this._$on.apply(this, _args);\n    //         }else{\n    //         // click(options) 或者 click()\n    //             this._$trigger.apply(this, _args);\n    //         }\n    //         return this;\n    //     }.autoSet())\n    // });\n    // 把原型还回去, WARN:千万注意\n    _fn.reset();\n    \n    if (CMPT){\n        nej.$ = $;\n    }\n    \n    return $;\n});\n\n"
  },
  {
    "path": "src/util/chain/README.md",
    "content": "# chainable.js\n类似于jQuery的链式操作模块，\n命名空间  nej.$\n\n## 使用\n\n### 1. 引入依赖\n\n```javascript\n// Push 进了 nej所有节点相关API的\ndefine('xxx模块', ['{lib}util/chain/chainable.js'], f)`\n\n// 如果你不习惯使用链式使用nej的原API，但是又有对新API的需求, 你可以只引入NodeList.js\ndefine('xxx模块', ['{lib}util/chain/NodeList.js'], f);\n\n```\n\n\n### 2. 使用\n\n```\n\n\n\n\n## API介绍\n\n### 1. 原有API支持列表(通过)\n\n\n\n\n"
  },
  {
    "path": "src/util/chain/chainable.js",
    "content": "/*\n * ------------------------------------------\n * 利用NEJ原有API包装成链式调用风格API， * @version  0.1\n * @author hzzhenghaibo\n * ------------------------------------------\n */\nNEJ.define([\n    './NodeList.js'\n],function(_l){\n    return _l;\n});\n"
  },
  {
    "path": "src/util/chain/test/chainable.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>链式调用测试</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n        <script type=\"text/javascript” src=”https://getfirebug.com/firebug-lite.js\"></script>\n        <style type=\"text/css\">\n            .js-hover{\n                background: #330 !important;\n            }\n        </style>\n    </head>\n    <body>\n        <a href=\"javascript:(function(){var d=document, s=d.getElementById('firebug-lite');if(s!=null)return;s=d.createElement('script');s.type='text/javascript';s.src='https://getfirebug.com/firebug-lite.js';d.body.appendChild(s);})();void(0);\">firebug-lite</a>\n        <h1 id=\"qunit-header\">Qunit chart test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <!-- chainable test section -->\n        <div id=\"chainable\">\n            <div id=\"chainable-header\" class=\"o1\">\n                <ul id=\"list\">\n                    <li class=\"section class1\"></li>\n                    <li class=\"section class2\"></li>\n                    <li class=\"section class3\"></li>\n                    <li class=\"section class4\"></li>\n                    <li class=\"section class5\"></li>\n                    <li class=\"section class6\"></li>\n                    <li class=\"section class7\"></li>\n                    <li class=\"section class8\"></li>\n                    <li class=\"section class9\"></li>\n                    <li class=\"section class10\"></li>\n                    <li class=\"section class11\"></li>\n                    <li class=\"section class12\"></li>\n                    <li class=\"section class13\"></li>\n                    <li class=\"section class14\"></li>\n                    <li class=\"section class15\"></li>\n                    <li class=\"section class16\"></li>\n                </ul>\n            </div>\n            <div id=\"chainable-body\" class=\"o2\"></div>\n            <div id=\"chainable-footer\" class=\"o2\"></div>\n        </div>\n        <div id=\"chain2\">\n            <ul class=\"u1\">\n                <li class=\"l11\"></li>\n                <li class=\"l12\"></li>\n                <li class=\"l13\"></li>\n            </ul>\n            <ul class=\"u2\">\n                <li class=\"l21\"></li>\n                <li class=\"l22\"></li>\n                <li class=\"l23\"></li>\n            </ul>\n        </div>\n\n        <div id=\"mani\">\n            <dl id=\"mani-dl\">\n                <dt></dt>\n                <dd></dd>\n            </dl>\n        </div>\n\n        <div id=\"mani-c\">\n            <div></div>\n            <div></div>\n        </div>\n\n        <div id=\"event\">\n            <ol>\n                <li>哈哈</li>\n                <li>哈哈</li>\n                <li>哈哈</li>\n            </ol>\n            <ol>\n                <li>哈哈</li>\n                <li>哈哈</li>\n                <li>哈哈</li>\n            </ol>\n        </div>\n\n        <div id=\"nej\">\n            <div class=\"style\">\n                <ul>\n                    <li>style1</li>\n                    <li>style2</li>\n                    <li>style3</li>\n                </ul>\n            </div>\n            <div class=\"attr\"></div>\n        </div>\n\n        <div id=\"html-text\">\n            <div class=\"content\"></div>\n            <div class=\"content\"></div>\n            <input type=\"text\"/>\n            <textarea></textarea>\n        </div> \n        <div id=\"event-fixture\">\n            <div class=\"c1\">哈哈哈</div>\n            <div class=\"c2\">hahah</div>\n        </div>\n        <!-- /end chainable -->\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./chainable.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/chain/test/chainable.test.js",
    "content": "\n\nvar perfTest = function(fn, times){\n    var date =  +new Date()\n    times = times || 0;\n    for(var i = 0;i< times;i++){\n        fn()\n    }\n    console.log(+new Date - date)\n};\nvar f = function() {\n    module(\"chainable\");\n\n    var _ = NEJ.P,\n        _e = _('nej.e'),\n        _u = _(\"nej.u\"),\n        _v = _(\"nej.v\"),\n        $ = _('nej.$'),\n        _x = _('nej.x');\n\n\n    test('NodeList initialize', function() {\n\n        // 正常千万别这么写\n        var _res = $(\"#chainable li:nth-child(2n+1)\"),\n            _len = nes.all(\"#chainable li:nth-child(2n+1)\").length;\n\n        equal($(\"#chainable li:nth-child(2n+1)\").length, _len, \"数量与节点数量一致\")\n\n        equal($(\"\").length, 0, \"可以传入不合法参数，返回空_NodeList对象\");\n        equal($(nes.all(\"#chainable\"))[0], $(\"#chainable\")[0], \"可以直接传入节点数组\");\n        equal($(nes.one(\"#chainable\"))[0], nes.one(\"#chainable\"), \"可以直接传入单节点\")\n        var _node = $(\"#chainable\")\n        notEqual(_node, $(_node), \"重新包装会返回新对象\")\n\n        deepEqual($(\"#chainable li:nth-child(2n+1)\")._$get(), nes.all(\"#chainable li:nth-child(2n+1)\"), \"_$get返回真实数组\")\n        deepEqual($(\"#chainable li:nth-child(2n+1)\")._$get(1), nes.all(\"#chainable li:nth-child(2n+1)\")[1], \"传入下标，_$get返回数组中的值\")\n\n        ok(!Function.prototype.splitProcee, \"原型修复splitProcess\")\n        ok(!Function.prototype.autoSet, \"原型修复autoSet\")\n    })\n\n    test('NodeList implement', function() {\n        var fn1 = function() {\n                return \"fn1\"\n            }\n        var fn2 = function() {\n                return \"fn2\"\n            }\n        var fn3 = function() {\n                return \"fn3\"\n            }\n        $._$implement({_$test1: fn1})\n        deepEqual($()._$test1, fn1)\n        $._$implement({\n            \"fn2\": fn2,\n            \"fn3\": fn3\n        })\n        deepEqual($().fn2, fn2, \"也可以传入对象数组\")\n\n        // 2. 静态方法的 implement\n        // no return static\n        var staticFn = function(_node) {\n                _e._$setStyle(_node, \"height\", \"40px\");\n                return _e\n            }\n            // get static\n        var staticFn2 = function(_node) {\n                return 20\n            }\n\n        $._$implement(\"sfn1\", staticFn, {\n            statics: true\n        })\n        $._$implement(\"sfn2\", staticFn2, {\n            statics: true\n        })\n\n        var _list = $(\"#chainable li\")\n        equal(_list.sfn1(), _list, \"set型方法可链式\");\n        var _notAll = false\n        _u._$forEach(_list, function(_node) {\n            if (_e._$getStyle(_node, \"height\") !== \"40px\") _notAll = true\n        })\n\n        ok(_notAll === false, \"所有的节点都被影响了\")\n\n        equal(_list.sfn2(), 20, \"get型方法不可链式，且有返回值\");\n    })\n    \n\n    module(\"NEJ 方法merge\")\n    test(\"_$style 和 _$attr\", function(){\n        $style = $(\"#nej .style\");\n        $attr = $(\"#nej .attr\"); \n\n        $style._$style(\"width\", \"80px\");\n        equal($style._$style(\"width\"), \"80px\", \"style get与set down\"); \n\n        $style._$style({\n             height: \"80px\",\n             width: \"40px\",\n             backgroundColor:\"#ccc\"\n        });\n        deepEqual($style._$style([\"height\", \"width\"]),{\"height\":\"80px\",\"width\":\"40px\"}, \"style 多重getter与setter down\")\n\n        $attr._$attr(\"title\", \"haha\")\n        equal($attr._$attr(\"title\"), \"haha\", \"attr get与set down\"); \n        $attr._$attr({\n             title: \"title\",\n             rel:\"link\"\n        });\n        deepEqual($attr._$attr([\"title\", \"rel\"]),{\"title\":\"title\",\"rel\":\"link\"}, \"attr 多重getter与setter down\")\n\n    });\n    test(\"nej方法merge\", function(){\n        _x._$title = function(_node, title){\n            if(title) _node.title = title\n            else return _node.title\n        }\n\n        _x.isChange = true;\n\n        $(\"body,div\")._$title(\"haha\")\n        equal($(\"body,div\")._$title(), \"haha\", \"get\")\n        $(\"body,div\")._$title(\"haha2\")\n        equal($(\"body,div\")._$title(), \"haha2\", \"setter\")\n\n\n        //  var _list =  [//class相关\n        // \"addClassName\", \"delClassName\", \"hasClassName\", \"replaceClassName\", \"toggle\",// class相关\n        // //css相关\n        // \"setStyle\", \"getStyle\",\"css3d\", \"style\", \"offset\", \"getScrollViewPort\", \n        // // 动画 特效 UI\n        // \"fixed\", \"effect\", \"fade\", \"focus\", \"highlight\", \"hover\", \"page\", \"placeholder\", \"tab\", \"wrapInline\",\n        // // 属性相关\n        // \"attr\", \"dataset\",\n        // // 节点\n        // \"remove\", \"removeByEC\",\n        // // // 杂项\n        // \"dom2xml\",\"bindClearAction\",\"bindCopyAction\", \"counter\",\"addEvent\", \"clearEvent\", \"delEvent\", \"dispatchEvent\"]\n        // var _node = $(\"body\"), num= 0;\n        // _u._$forEach(_list, function(_name){\n        //     if(typeof _node[\"_$\" + _name] === \"function\"){\n        //         num++\n        //     }\n        // })\n        // equal(num, _list.length, \"全部方法merge\")\n    })\n\n    module(\"Base:过滤、逻辑\")\n    test(\"_$fiter、_$map、_$forEach\", function() {\n        deepEqual(nes.all(\"#chainable li:nth-child(even)\"), $(\"#chainable li\")._$filter(\":nth-child(even)\")._$get(), \"fitler 可传入 选择器\")\n        var _res = $(\"#chainable li\")._$filter(function(_node, _index) {\n            return _index % 2 === 0; // 注意下表是从0开始\n        })._$get();\n\n        deepEqual(nes.all(\"#chainable li:nth-child(odd)\"), _res, \"fitler 可以传入 函数\")\n\n        var _res2 = $(\"#chainable li\")._$map(function(_node){\n            return _node\n        })\n        deepEqual(nes.all(\"#chainable li:nth-child(odd)\"), _res, \"fitler 可以传入 函数\");\n    })\n    module(\"节点遍历\")\n    test(\"_$prev、_$next、_$parent、_$children \", function() {\n       var _res = $(\"#chainable li\")._$next(\":nth-child(odd)\", true)._$get();\n       deepEqual(_res, nes.all(\"#chainable li ~ :nth-child(odd)\"), \"_$next all 成功返回\")\n\n       var _res = $(\"#chainable-footer\")._$prev(true)._$get();\n       $._$uniqueSort(_res) // 不保证是有序的\n       deepEqual(_res, nes.all(\"#chainable-header, #chainable-body\"), \"_$prev all 成功返回\")\n       var _res = $(\"#chainable-footer\")._$prev()._$get();\n       deepEqual(_res, nes.all(\"#chainable-body\"), \"_$prev single 成功返回\")\n\n       var _res = $(\"#chainable-header\")._$next(true)._$get();\n       deepEqual(_res, nes.all(\"#chainable-body, #chainable-footer\"), \"_$next all 成功返回\")\n       var _res = $(\"#chainable-header\")._$next()._$get();\n       deepEqual(_res, nes.all(\"#chainable-body\"), \"_$next single 成功返回\")\n\n       var _parent = $('#chainable li')._$parent(\"ul\", true)._$get();\n       deepEqual(_parent, nes.all(\"#chainable ul\"), \"_$parent all 成功返回\")\n\n       var _parent = $('#chainable li')._$parent(\"ul,div\", true)._$sort()._$get();\n       deepEqual(_parent, nes.all(\"#chainable ul, #chainable, #chainable-header\"), \"_$parent all 成功返回\")\n\n       var _parent = $('#chainable li')._$parent(\"ul, div\")._$get();\n\n       // 全部兄弟元素\n       var _siblings = $(\"#chainable li:last-child\")._$siblings(\"li\")._$sort()._$get();\n\n       deepEqual(_siblings, nes.all(\"#chainable li:not(:last-child)\"), \"siblings会选择所有满足选择器的兄弟节点(但不包括li)\");\n\n\n       var _children = $(\"#chain2\")._$children(\"ul\")._$get()\n       deepEqual(_children, nes.all(\"#chain2 > ul\"), \"可以取到直接子节点\");\n\n       var _children = $(\"#chain2\")._$children(\"li:first-child\")._$get()\n       deepEqual(_children, [], \"不会查找非直接子节点\")\n\n       // 加all 参数 使用全体子节点查找\n       var _children = $(\"#chain2\")._$children(\"li:first-child\", true)._$get()\n       deepEqual(_children, nes.all(\"li:first-child\", nes.one(\"#chain2\")))\n    })\n    module(\"事件Event\")\n    test(\"Events: base _$on, $off, $trigger\", function() {\n        var _locals = {\"0\":0}\n        var _handle1 = function(e){_locals[0]++;}//每次递增1\n        var _handleForMultEvents = function(){_locals[1] == (_locals[1]||0)+1;}\n        // 可以\n        var $node = $(\"#chain2\");\n        var _uid = $._$uid($node[0]);\n\n        // step 1 确保 原有调用方式不错\n        // $node._$on(\"click\", _handle1)\n        _v._$addEvent($node[0],\"click\",_handle1)\n        equal($._delegateHandlers[_uid], undefined, \"不使用事件代理，不会保存handler\");\n        _v._$dispatchEvent($node[0],\"click\",{})\n        equal(_locals[0],1, \"被正确触发\")\n        \n        $node._$trigger(\"click\");\n        equal(_locals[0],2, \"被正确触发\")\n        $node._$off(\"click\",_handle1);\n        $node._$trigger(\"click\")\n        equal(_locals[0],2, \"不再被触发，因为已经解除绑定\")\n\n        var _prev = _locals[0]\n        $node._$on([\"click\",\"mouseover\", \"mouseout\"], _handle1)\n        // $node._$trigger(\"click\")\n        $node._$trigger([\"click\", \"mouseover\"])\n        equal(_locals[0],_prev+2, \"可以使用数组绑定多个事件, 并且可以trigger多个事件\")\n        var _prev = _locals[0];\n        $node._$off([\"click\",\"mouseover\"])\n        $node._$trigger([\"click\",\"mouseover\"])\n        equal(_locals[0],_prev, \"click, mouseover, 无法触发因为都被解绑了\")\n        $node._$trigger(\"mouseout\",{hello:1})\n        equal(_locals[0],_prev+1, \"mouseout仍然存\")\n        $node._$off()\n        $node._$trigger([\"mouseout\",\"click\",\"mouseover\"])\n        equal(_locals[0],_prev+1, \"所有事件都被取消\")\n\n        var _prev = _locals[0]\n        var _handle2 = function(e){_locals[0]+= e.step||1}\n        $node._$on([\"mouseout\",\"click\",\"mouseover\"], _handle2)\n\n        $node._$trigger(\"mouseout\", {step:2})\n        equal(_locals[0],_prev+2, \"简单参数传入\")\n\n        var _prev = _locals[0];\n        $node._$trigger({\n            \"mouseout\":{step:3},\n            \"mouseover\":{step:2}\n        })\n        equal(_locals[0],_prev+5, \"多重trigger并传入参数\")\n\n        var _prev = _locals[0];\n        $node._$trigger([\"mouseout\",\"click\"],{step:3})\n        equal(_locals[0],_prev+6, \"多个trigger并传入同一个参数\")\n\n\n    })\n\n    test(\"_event fixtue\", function(){\n        $node = $(\"#event-fixture\");\n        $node._$on(\"click\", function(_e){\n            ok(_e.__fixed, \"有__fixed标示说明被patch\")\n        })\n        $node._$trigger(\"click\", {hello:1});\n    });\n\n    // test(\"_$click、_$dblclick....\", function(){\n    // //     var $node = $(\"#event\");\n    // //     var _locals = [0]\n    // //     var _methods = (\"click dbclick blur change focus focusin focusout keydown keypress \"+ \n    // // \"keyup mousedown mouseover mouseup mousemove mouseout scroll select submit\").split(\" \");\n\n    // //     _u._$forEach(_methods, function(_method, _index){\n    // //         ok(typeof $node[\"_$\"+_method] === \"function\", _method+\"方法存在\");\n    // //     })\n\n    // //     $node._$click(function(){\n    // //         _locals[0]++;\n    // //     })\n    // //     $node._$click()\n\n    // //     equal(_locals[0],1, \"可以通过_$click的方式绑定事件和触发事件\")\n\n    // //     _locals[1] = 0;\n\n    // //     $node._$click({ //暂时手动测试 事件代理 @UI\n    // //         \"li\":function(e){\n    // //             alert(\"li click\")\n    // //             console.log(e.hello)\n    // //         }\n    // //     })\n    // })\n\n    module(\"节点操作\")\n    test(\"节点操作:_$clone等\",function(){\n\n        var $mani = $(\"#mani\");\n\n        var $cmani = $mani._$clone();//不深度复制\n\n        notEqual($._$uid($mani[0]), $._$uid($cmani[0]), \"节点标示会被重新设置\")\n        ok(!$cmani[0].getAttribute(\"id\"), \"节点ID被清空\")\n        equal($cmani[0].innerHTML, \"\", \"不会复制子节点\")\n\n        var $cmani2 = $mani._$clone(true);//不深度复制\n        var $cmaniDl = $cmani2._$children(\"dl\");\n        notEqual($._$uid($mani[0]), $._$uid($cmani[0]), \"节点标示会被重新设置\")\n        ok(!!$cmaniDl,\"会复制子节点\")\n        ok(!$cmaniDl[0].getAttribute(\"id\"), \"子节点ID也被清空\")\n\n    });\n    // test(\"_$insert、_$insert2、_$top2....\", function(){\n    //     var $node = $(\"#chain2\");            \n    //     var _methods = \"bottom top before after bottom2 top2 before2 after2\".split(\" \");\n\n    //     // 首先确定所有方法已经都存在了\n    //     _u._$forEach(_methods, function(_method){\n    //         ok(typeof $node[\"_$\"+_method] === \"function\", _method+\"方法存在\")\n    //     })\n\n    //     var $mani = $(\"#mani\");\n    //     var $maniC = $(\"#mani-c div\") //mani container\n\n    //     // 分别测试 bottom top before after\n    //     var $cmani = $mani._$clone(true);\n    //     var $cmani2 = $mani._$clone(true);\n    //     var $cmani3 = $mani._$clone(true);\n    //     var $cmani4 = $mani._$clone(true);\n\n    //     equal($cmani[0], $mani._$parent()._$bottom($cmani)._$children()._$last(), \"复制的节点cmani被插入底部\");\n    //     equal($cmani2[0], $mani._$parent()._$top($cmani2)._$children()._$first(), \"复制的节点cmani2被插入顶部\");\n    //     equal($cmani3[0], $mani._$before($cmani3)._$prev()._$first(), \"复制的节点cmani3被插入cmani之前\");\n    //     equal($cmani4[0], $mani._$after($cmani4)._$next()._$first(), \"复制的节点cmani4被插入cmani之后\");\n\n    //     equal($maniC.length, 2, \"要被插入的节点集有两个元素\")\n    //     var $cmani = $mani._$clone(true);\n    //     $cmani._$insert2(\"#mani-c div\")\n    //     equal($maniC._$children().length, 2, \"两个元素分别被插入了两个节点\")\n\n    // });\n    test(\"属性操作\", function(){\n        var $node = $(\"#html-text .content\");\n        equal($node._$text(\"haha\"), $node, \"$text可链式\")\n        equal($node._$text(), \"haha\", \"可取得textContent值\")\n        equal($node._$last(true)._$text(), \"haha\", \"多个节点也可以赋值\")\n\n        equal($node._$html(\"haha\"), $node, \"$html\")\n        equal($node._$html(), \"haha\", \"可取得\")\n        equal($node._$last(true)._$html(), \"haha\", \"_$html多个节点也可以赋值\")\n\n        var $input = $(\"#html-text\")._$children(\"input,textarea\");\n        equal($input._$val(\"haha\"), $input, \"$val可链式\")\n        equal($input._$val(), \"haha\", \"可取得value\")\n        equal($input._$last(true)._$val(), \"haha\", \"多个节点也可以赋值\")\n\n    })\n\n    module(\"链式操作\")\n    test(\"基本操作:UI\", function(){\n        // 获取 奇数行的代码 设置样式\n        deepEqual(\n        $(\"#chainable li:nth-child(odd)\")._$style({\n            \"background\": \"#cca\",\n            \"cursor\": \"pointer\"\n        })\n        // 然后抛弃他们 找他们的下一个位置条件满足是4倍数的兄弟节点并设置样式\n        ._$next(\":nth-child(2n)\")._$style({\n            \"background\": \"#a19\",\n            \"cursor\": \"help\"\n        })\n        // 过滤出其中是4倍数的行,并绑定click事件\n        ._$filter(\":nth-child(4n)\")._$on('click', function(_e) {\n            $(this)._$style(\"background\", \"#111\");\n        // 并给他们中的第一行设置边框\n        })._$get(1, true)._$style(\"border\", \"3px solid #222\")\n        // 找到父节点div并且有chainable的id并且设置样式\n        ._$parent(\"div#chainable\")._$style({\n            width: \"800px\",\n            left: \"300px\",\n            position:\"absolute\"\n        // 绑定事件以及代理事件\n        })._$on({\n            \"click\" :function(){\n                var div = document.createElement(\"div\")\n                div.innerHTML = \"haha插入一行\"\n                //每次点击插入一行\n                $(this)._$insert(div, \"bottom\");\n            },\n            \"mouseover li:nth-child(odd)\":function(_e){\n                _e.preventDefault();\n                if(!_e.__fixed) alert(\"delegate event object not fixed\")\n                this._isLight = !this._isLight;\n                // 每次点击改变背景色\n                $(this)._$style(\"background-color\", this._isLight? \"#cca\":\"#331\")\n            },\n            \"click li:nth-child(odd)\":function(_e){\n                alert(\"_e\");\n            }\n        // 获得样式值\n        })._$off(\"click li:nth-child(odd)\")//这个无法触发\n        ._$style([\"width\", \"left\"]), {width: \"800px\", left: \"300px\"}, \" 链式操作成功，并且getter返回值成功\")\n        \n        $(\"li\")._$on(\"contextmenu\",function(_e){\n            alert(_e.which)\n            alert(\"contextmenu\")\n        })\n\n    })\n\n}\ndefine('{pro}chainable.test.js', ['{lib}util/chain/chainable.js'], f);\n\n"
  },
  {
    "path": "src/util/chain/test/fixture.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <title>链式调用功能Test</title>\n    <script src=\"../../../src/define.js?pro=./\"></script>\n    <link href=\"http://www.w3.org/StyleSheets/TR/W3C-WG-NOTE.css\"rel=stylesheet type=\"text/css\"></head>\n<body>\n    <h2>功能TEST</h2>\n    <div id=\"chain-fixtrue\">\n        <table class=\"proptable\">\n            <thead>\n                <tr>\n                    <th>Name</th>\n                    <th>Values</th>\n                    <th>Initial value</th>\n                    <th>Applies to</th>\n                    <th>Inherited?</th>\n                    <th>Percentages</th>\n                    <th>Media</th>\n                </tr>\n            </thead>\n            <tbody>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/colors.html#propdef-background-attachment\">\n                            <code>background-attachment</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        scroll | fixed |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>scroll</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/colors.html#propdef-background-color\">\n                            <code>background-color</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/css3-color/#colorunits\">&lt;color&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>transparent</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/colors.html#propdef-background-image\">\n                            <code>background-image</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-uri\">&lt;uri&gt;</a>\n                        | none |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>none</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/colors.html#propdef-background-position\">\n                            <code>background-position</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        [ [\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage\">&lt;percentage&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        | left | center | right ] [\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage\">&lt;percentage&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        | top | center | bottom ]? ] | [ [ left | center | right ] || [ top |\n      center | bottom ] ] |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>0% 0%</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>refer to the size of the box itself</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/colors.html#propdef-background-repeat\">\n                            <code>background-repeat</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        repeat | repeat-x | repeat-y | no-repeat |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>repeat</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/colors.html#propdef-background\">\n                            <code>background</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        [\n                        <a href=\"http://www.w3.org/TR/CSS21/colors.html#propdef-background-color\">\n                            ‘\n                            <code class=\"property\">background-color</code>\n                            ’\n                        </a>\n                        ||\n                        <a href=\"http://www.w3.org/TR/CSS21/colors.html#propdef-background-image\">\n                            ‘\n                            <code class=\"property\">background-image</code>\n                            ’\n                        </a>\n                        ||\n                        <a href=\"http://www.w3.org/TR/CSS21/colors.html#propdef-background-repeat\">\n                            ‘\n                            <code class=\"property\">background-repeat</code>\n                            ’\n                        </a>\n                        ||\n                        <a href=\"http://www.w3.org/TR/CSS21/colors.html#propdef-background-attachment\">\n                            ‘\n                            <code class=\"property\">background-attachment</code>\n                            ’\n                        </a>\n                        ||\n                        <a href=\"http://www.w3.org/TR/CSS21/colors.html#propdef-background-position\">\n                            <code>background-position</code>\n                        </a>\n                        ]\n      |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>see individual properties</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>\n                        allowed on ‘\n                        <code class=\"property\">background-position</code>\n                        ’\n                    </td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/tables.html#propdef-border-collapse\">\n                            <code>border-collapse</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        collapse | separate |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>separate</td>\n                    <td>\n                        ‘\n                        <code class=\"property\">table</code>\n                        ’ and ‘\n                        <code class=\"property\">inline-table</code>\n                        ’ elements\n                    </td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-color\">\n                            <code>border-color</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        [\n                        <a href=\"http://www.w3.org/TR/css3-color/#colorunits\">&lt;color&gt;</a>\n                        ]{1,4} |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>see individual properties</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/tables.html#propdef-border-spacing\">\n                            <code>border-spacing</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        ?\n      |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>0</td>\n                    <td>\n                        ‘\n                        <code class=\"property\">table</code>\n                        ’ and ‘\n                        <code class=\"property\">inline-table</code>\n                        ’ elements&nbsp;\n                    </td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-style\">\n                            <code>border-style</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#value-def-border-style\">&lt;border-style&gt;</a>\n                        {1,4}\n      |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>see individual properties</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-top\">\n                            <code>border-top</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-right\">\n                            <code>border-right</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-bottom\">\n                            <code>border-bottom</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-left\">\n                            <code>border-left</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        [\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#value-def-border-width\">&lt;border-width&gt;</a>\n                        ||\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#value-def-border-style\">&lt;border-style&gt;</a>\n                        ||\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-top-color\">\n                            <code>border-top-color</code>\n                        </a>\n                        ] |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>see individual properties</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-top-color\">\n                            <code>border-top-color</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-right-color\">\n                            <code>border-right-color</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-bottom-color\">\n                            <code>border-bottom-color</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-left-color\">\n                            <code>border-left-color</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/css3-color/#colorunits\">&lt;color&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>\n                        the value of the ‘\n                        <code class=\"property\">color</code>\n                        ’\n      property\n                    </td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-top-style\">\n                            <code>border-top-style</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-right-style\">\n                            <code>border-right-style</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-bottom-style\">\n                            <code>border-bottom-style</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-left-style\">\n                            <code>border-left-style</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#value-def-border-style\">&lt;border-style&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>none</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-top-width\">\n                            <code>border-top-width</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-right-width\">\n                            <code>border-right-width</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-bottom-width\">\n                            <code>border-bottom-width</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-left-width\">\n                            <code>border-left-width</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#value-def-border-width\">&lt;border-width&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>medium</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-width\">\n                            <code>border-width</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#value-def-border-width\">&lt;border-width&gt;</a>\n                        {1,4}\n      |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>see individual properties</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border\">\n                            <code>border</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        [\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#value-def-border-width\">&lt;border-width&gt;</a>\n                        ||\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#value-def-border-style\">&lt;border-style&gt;</a>\n                        ||\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-border-top-color\">\n                            <code>border-top-color</code>\n                        </a>\n                        ] |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>see individual properties</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visuren.html#propdef-bottom\">\n                            <code>bottom</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage\">&lt;percentage&gt;</a>\n                        | auto |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>auto</td>\n                    <td>positioned elements</td>\n                    <td>no</td>\n                    <td>refer to height of containing block</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/tables.html#propdef-caption-side\">\n                            <code>caption-side</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        top | bottom |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>top</td>\n                    <td>\n                        ‘\n                        <code class=\"property\">table-caption</code>\n                        ’ elements\n                    </td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visuren.html#propdef-clear\">\n                            <code>clear</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        none | left | right | both |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>none</td>\n                    <td>block-level elements</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visufx.html#propdef-clip\">\n                            <code>clip</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/visufx.html#value-def-shape\">&lt;shape&gt;</a>\n                        | auto |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>auto</td>\n                    <td>absolutely positioned elements</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/css3-color/#foreground\">\n                            <code>color</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/css3-color/#colorunits\">&lt;color&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>depends on user agent</td>\n                    <td>&nbsp;</td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/generate.html#propdef-content\">\n                            <code>content</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        normal | none | [\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-string\">&lt;string&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-uri\">&lt;uri&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-counter\">&lt;counter&gt;</a>\n                        | attr(\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\">&lt;identifier&gt;</a>\n                        )\n      | open-quote | close-quote | no-open-quote | no-close-quote ]+ |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>normal</td>\n                    <td>:before and :after pseudo-elements</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#all-media-group\">all</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/generate.html#propdef-counter-increment\">\n                            <code>counter-increment</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        [\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\">&lt;identifier&gt;</a>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-integer\">&lt;integer&gt;</a>\n                        ?\n      ]+ | none |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>none</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#all-media-group\">all</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/generate.html#propdef-counter-reset\">\n                            <code>counter-reset</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        [\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\">&lt;identifier&gt;</a>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-integer\">&lt;integer&gt;</a>\n                        ?\n      ]+ | none |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>none</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#all-media-group\">all</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/ui.html#propdef-cursor\">\n                            <code>cursor</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        [ [\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-uri\">&lt;uri&gt;</a>\n                        ,]* [ auto | crosshair | default | pointer | move | e-resize |\n      ne-resize | nw-resize | n-resize | se-resize | sw-resize | s-resize |\n      w-resize | text | wait | help | progress ] ] |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>auto</td>\n                    <td>&nbsp;</td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n                        ,\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#interactive-media-group\">interactive</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visuren.html#propdef-direction\">\n                            <code>direction</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        ltr | rtl |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>ltr</td>\n                    <td>all elements, but see prose</td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visuren.html#propdef-display\">\n                            <code>display</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        inline | block | list-item | inline-block | table | inline-table |\n      table-row-group | table-header-group | table-footer-group | table-row |\n      table-column-group | table-column | table-cell | table-caption | none |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>inline</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#all-media-group\">all</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/tables.html#propdef-empty-cells\">\n                            <code>empty-cells</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        show | hide |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>show</td>\n                    <td>\n                        ‘\n                        <code class=\"property\">table-cell</code>\n                        ’ elements\n                    </td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visuren.html#propdef-float\">\n                            <code>float</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        left | right | none |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>none</td>\n                    <td>\n                        all, but see\n                        <a href=\"http://www.w3.org/TR/CSS21/visuren.html#dis-pos-flo\">9.7</a>\n\n                    </td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#propdef-font-family\">\n                            <code>font-family</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        [ [\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#value-def-family-name\">&lt;family-name&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#value-def-generic-family\">&lt;generic-family&gt;</a>\n                        ] [,\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#value-def-family-name\">&lt;family-name&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#value-def-generic-family\">&lt;generic-family&gt;</a>\n                        ]* ] |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>depends on user agent</td>\n                    <td>&nbsp;</td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#propdef-font-size\">\n                            <code>font-size</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#value-def-absolute-size\">&lt;absolute-size&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#value-def-relative-size\">&lt;relative-size&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage\">&lt;percentage&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>medium</td>\n                    <td>&nbsp;</td>\n                    <td>yes</td>\n                    <td>refer to inherited font size</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#propdef-font-style\">\n                            <code>font-style</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        normal | italic | oblique |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>normal</td>\n                    <td>&nbsp;</td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#propdef-font-variant\">\n                            <code>font-variant</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        normal | small-caps |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>normal</td>\n                    <td>&nbsp;</td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#propdef-font-weight\">\n                            <code>font-weight</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600\n      | 700 | 800 | 900 |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>normal</td>\n                    <td>&nbsp;</td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#propdef-font\">\n                            <code>font</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        [ [\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#propdef-font-style\">\n                            ‘\n                            <code class=\"property\">font-style</code>\n                            ’\n                        </a>\n                        ||\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#propdef-font-variant\">\n                            ‘\n                            <code class=\"property\">font-variant</code>\n                            ’\n                        </a>\n                        ||\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#propdef-font-weight\">\n                            ‘\n                            <code class=\"property\">font-weight</code>\n                            ’\n                        </a>\n                        ]?\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#propdef-font-size\">\n                            ‘\n                            <code class=\"property\">font-size</code>\n                            ’\n                        </a>\n                        [ /\n                        <a href=\"http://www.w3.org/TR/CSS21/visudet.html#propdef-line-height\">\n                            ‘\n                            <code class=\"property\">line-height</code>\n                            ’\n                        </a>\n                        ]?\n                        <a href=\"http://www.w3.org/TR/CSS21/fonts.html#propdef-font-family\">\n                            <code>font-family</code>\n                        </a>\n                        ] | caption | icon | menu | message-box | small-caption | status-bar |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>see individual properties</td>\n                    <td>&nbsp;</td>\n                    <td>yes</td>\n                    <td>see individual properties</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visudet.html#propdef-height\">\n                            <code>height</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage\">&lt;percentage&gt;</a>\n                        | auto |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>auto</td>\n                    <td>\n                        all elements but non-replaced inline elements, table columns, and\n      column groups\n                    </td>\n                    <td>no</td>\n                    <td>see prose</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visuren.html#propdef-left\">\n                            <code>left</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage\">&lt;percentage&gt;</a>\n                        | auto |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>auto</td>\n                    <td>positioned elements</td>\n                    <td>no</td>\n                    <td>refer to width of containing block</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/text.html#propdef-letter-spacing\">\n                            <code>letter-spacing</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        normal |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>normal</td>\n                    <td>&nbsp;</td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visudet.html#propdef-line-height\">\n                            <code>line-height</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        normal |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-number\">&lt;number&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage\">&lt;percentage&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>normal</td>\n                    <td>&nbsp;</td>\n                    <td>yes</td>\n                    <td>refer to the font size of the element itself</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/generate.html#propdef-list-style-image\">\n                            <code>list-style-image</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-uri\">&lt;uri&gt;</a>\n                        | none |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>none</td>\n                    <td>\n                        elements with ‘\n                        <code class=\"css\">display:\n      list-item</code>\n                        ’\n                    </td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/generate.html#propdef-list-style-position\">\n                            <code>list-style-position</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        inside | outside |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>outside</td>\n                    <td>\n                        elements with ‘\n                        <code class=\"css\">display:\n      list-item</code>\n                        ’\n                    </td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/generate.html#propdef-list-style-type\">\n                            <code>list-style-type</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        disc | circle | square | decimal | decimal-leading-zero |\n      lower-roman | upper-roman | lower-greek | lower-latin | upper-latin |\n      armenian | georgian | lower-alpha | upper-alpha | none |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>disc</td>\n                    <td>\n                        elements with ‘\n                        <code class=\"css\">display:\n      list-item</code>\n                        ’\n                    </td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/generate.html#propdef-list-style\">\n                            <code>list-style</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        [\n                        <a href=\"http://www.w3.org/TR/CSS21/generate.html#propdef-list-style-type\">\n                            ‘\n                            <code class=\"property\">list-style-type</code>\n                            ’\n                        </a>\n                        ||\n                        <a href=\"http://www.w3.org/TR/CSS21/generate.html#propdef-list-style-position\">\n                            ‘\n                            <code class=\"property\">list-style-position</code>\n                            ’\n                        </a>\n                        ||\n                        <a href=\"http://www.w3.org/TR/CSS21/generate.html#propdef-list-style-image\">\n                            <code>list-style-image</code>\n                        </a>\n                        ] |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>see individual properties</td>\n                    <td>\n                        elements with ‘\n                        <code class=\"css\">display:\n      list-item</code>\n                        ’\n                    </td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-margin-right\">\n                            <code>margin-right</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-margin-left\">\n                            <code>margin-left</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#value-def-margin-width\">&lt;margin-width&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>0</td>\n                    <td>\n                        all elements except elements with table display types other than\n      table-caption, table and inline-table\n                    </td>\n                    <td>no</td>\n                    <td>refer to width of containing block</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-margin-top\">\n                            <code>margin-top</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-margin-bottom\">\n                            <code>margin-bottom</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#value-def-margin-width\">&lt;margin-width&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>0</td>\n                    <td>\n                        all elements except elements with table display types other than\n      table-caption, table and inline-table\n                    </td>\n                    <td>no</td>\n                    <td>refer to width of containing block</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-margin\">\n                            <code>margin</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#value-def-margin-width\">&lt;margin-width&gt;</a>\n                        {1,4}\n      |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>see individual properties</td>\n                    <td>\n                        all elements except elements with table display types other than\n      table-caption, table and inline-table\n                    </td>\n                    <td>no</td>\n                    <td>refer to width of containing block</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visudet.html#propdef-max-height\">\n                            <code>max-height</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage\">&lt;percentage&gt;</a>\n                        | none |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>none</td>\n                    <td>\n                        all elements but non-replaced inline elements, table columns, and\n      column groups\n                    </td>\n                    <td>no</td>\n                    <td>see prose</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visudet.html#propdef-max-width\">\n                            <code>max-width</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage\">&lt;percentage&gt;</a>\n                        | none |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>none</td>\n                    <td>\n                        all elements but non-replaced inline elements, table rows, and row\n      groups\n                    </td>\n                    <td>no</td>\n                    <td>refer to width of containing block</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visudet.html#propdef-min-height\">\n                            <code>min-height</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage\">&lt;percentage&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>0</td>\n                    <td>\n                        all elements but non-replaced inline elements, table columns, and\n      column groups\n                    </td>\n                    <td>no</td>\n                    <td>see prose</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visudet.html#propdef-min-width\">\n                            <code>min-width</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage\">&lt;percentage&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>0</td>\n                    <td>\n                        all elements but non-replaced inline elements, table rows, and row\n      groups\n                    </td>\n                    <td>no</td>\n                    <td>refer to width of containing block</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/css3-color/#transparency\">\n                            <code>opacity</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-number\">&lt;number&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>1</td>\n                    <td>all</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/page.html#propdef-orphans\">\n                            <code>orphans</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-integer\">&lt;integer&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>2</td>\n                    <td>block container elements</td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n                        ,\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#paged-media-group\">paged</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/ui.html#propdef-outline-color\">\n                            <code>outline-color</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/css3-color/#colorunits\">&lt;color&gt;</a>\n                        |\n      invert |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>invert</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n                        ,\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#interactive-media-group\">interactive</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/ui.html#propdef-outline-style\">\n                            <code>outline-style</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#value-def-border-style\">&lt;border-style&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>none</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n                        ,\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#interactive-media-group\">interactive</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/ui.html#propdef-outline-width\">\n                            <code>outline-width</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#value-def-border-width\">&lt;border-width&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>medium</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n                        ,\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#interactive-media-group\">interactive</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/ui.html#propdef-outline\">\n                            <code>outline</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        [\n                        <a href=\"http://www.w3.org/TR/CSS21/ui.html#propdef-outline-color\">\n                            ‘\n                            <code class=\"property\">outline-color</code>\n                            ’\n                        </a>\n                        ||\n                        <a href=\"http://www.w3.org/TR/CSS21/ui.html#propdef-outline-style\">\n                            ‘\n                            <code class=\"property\">outline-style</code>\n                            ’\n                        </a>\n                        ||\n                        <a href=\"http://www.w3.org/TR/CSS21/ui.html#propdef-outline-width\">\n                            <code>outline-width</code>\n                        </a>\n                        ] |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>see individual properties</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n                        ,\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#interactive-media-group\">interactive</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visufx.html#propdef-overflow\">\n                            <code>overflow</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        visible | hidden | scroll | auto |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>visible</td>\n                    <td>block containers</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-padding-top\">\n                            <code>padding-top</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-padding-right\">\n                            <code>padding-right</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-padding-bottom\">\n                            <code>padding-bottom</code>\n                        </a>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-padding-left\">\n                            <code>padding-left</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#value-def-padding-width\">&lt;padding-width&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>0</td>\n                    <td>\n                        all elements except table-row-group, table-header-group,\n      table-footer-group, table-row, table-column-group and table-column\n                    </td>\n                    <td>no</td>\n                    <td>refer to width of containing block</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#propdef-padding\">\n                            <code>padding</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/box.html#value-def-padding-width\">&lt;padding-width&gt;</a>\n                        {1,4}\n      |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>see individual properties</td>\n                    <td>\n                        all elements except table-row-group, table-header-group,\n      table-footer-group, table-row, table-column-group and table-column\n                    </td>\n                    <td>no</td>\n                    <td>refer to width of containing block</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/page.html#propdef-page-break-after\">\n                            <code>page-break-after</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        auto | always | avoid | left | right |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>auto</td>\n                    <td>block-level elements (but see text)</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n                        ,\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#paged-media-group\">paged</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/page.html#propdef-page-break-before\">\n                            <code>page-break-before</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        auto | always | avoid | left | right |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>auto</td>\n                    <td>block-level elements (but see text)</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n                        ,\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#paged-media-group\">paged</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside\">\n                            <code>page-break-inside</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        avoid | auto |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>auto</td>\n                    <td>block-level elements (but see text)</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n                        ,\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#paged-media-group\">paged</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visuren.html#propdef-position\">\n                            <code>position</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        static | relative | absolute | fixed |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>static</td>\n                    <td>&nbsp;</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/generate.html#propdef-quotes\">\n                            <code>quotes</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        [\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-string\">&lt;string&gt;</a>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-string\">&lt;string&gt;</a>\n                        ]+\n      | none |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>depends on user agent</td>\n                    <td>&nbsp;</td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visuren.html#propdef-right\">\n                            <code>right</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage\">&lt;percentage&gt;</a>\n                        | auto |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>auto</td>\n                    <td>positioned elements</td>\n                    <td>no</td>\n                    <td>refer to width of containing block</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/tables.html#propdef-table-layout\">\n                            <code>table-layout</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        auto | fixed |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>auto</td>\n                    <td>\n                        ‘\n                        <code class=\"property\">table</code>\n                        ’ and ‘\n                        <code class=\"property\">inline-table</code>\n                        ’ elements\n                    </td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/text.html#propdef-text-align\">\n                            <code>text-align</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        left | right | center | justify |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>\n                        a nameless value that acts as ‘\n                        <code class=\"property\">left</code>\n                        ’ if ‘\n                        <code class=\"property\">direction</code>\n                        ’ is ‘\n                        <code class=\"property\">ltr</code>\n                        ’, ‘\n                        <code class=\"property\">right</code>\n                        ’ if ‘\n                        <code class=\"property\">direction</code>\n                        ’ is ‘\n                        <code class=\"property\">rtl</code>\n                        ’\n                    </td>\n                    <td>block containers</td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/text.html#propdef-text-decoration\">\n                            <code>text-decoration</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        none | [ underline || overline || line-through || blink ] |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>none</td>\n                    <td>&nbsp;</td>\n                    <td>no (see prose)</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/text.html#propdef-text-indent\">\n                            <code>text-indent</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage\">&lt;percentage&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>0</td>\n                    <td>block containers</td>\n                    <td>yes</td>\n                    <td>refer to width of containing block</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/text.html#propdef-text-transform\">\n                            <code>text-transform</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        capitalize | uppercase | lowercase | none |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>none</td>\n                    <td>&nbsp;</td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visuren.html#propdef-top\">\n                            <code>top</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage\">&lt;percentage&gt;</a>\n                        | auto |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>auto</td>\n                    <td>positioned elements</td>\n                    <td>no</td>\n                    <td>refer to height of containing block</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visuren.html#propdef-unicode-bidi\">\n                            <code>unicode-bidi</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        normal | embed | bidi-override |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>normal</td>\n                    <td>all elements, but see prose</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visudet.html#propdef-vertical-align\">\n                            <code>vertical-align</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        baseline | sub | super | top | text-top | middle | bottom |\n      text-bottom |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage\">&lt;percentage&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>baseline</td>\n                    <td>\n                        inline-level and ‘\n                        <code class=\"property\">table-cell</code>\n                        ’ elements\n                    </td>\n                    <td>no</td>\n                    <td>\n                        refer to the ‘\n                        <code class=\"property\">line-height</code>\n                        ’\n      of the element itself\n                    </td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visufx.html#propdef-visibility\">\n                            <code>visibility</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        visible | hidden | collapse |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>visible</td>\n                    <td>&nbsp;</td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/text.html#propdef-white-space\">\n                            <code>white-space</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        normal | pre | nowrap | pre-wrap | pre-line |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>normal</td>\n                    <td>&nbsp;</td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/page.html#propdef-widows\">\n                            <code>widows</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-integer\">&lt;integer&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>2</td>\n                    <td>block container elements</td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n                        ,\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#paged-media-group\">paged</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visudet.html#propdef-width\">\n                            <code>width</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-percentage\">&lt;percentage&gt;</a>\n                        | auto |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>auto</td>\n                    <td>\n                        all elements but non-replaced inline elements, table rows, and row\n      groups\n                    </td>\n                    <td>no</td>\n                    <td>refer to width of containing block</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/text.html#propdef-word-spacing\">\n                            <code>word-spacing</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        normal |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-length\">&lt;length&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>normal</td>\n                    <td>&nbsp;</td>\n                    <td>yes</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n                <tr>\n                    <th scope=\"row\">\n                        <a href=\"http://www.w3.org/TR/CSS21/visuren.html#propdef-z-index\">\n                            <code>z-index</code>\n                        </a>\n\n                    </th>\n                    <td>\n                        auto |\n                        <a href=\"http://www.w3.org/TR/CSS21/syndata.html#value-def-integer\">&lt;integer&gt;</a>\n                        |\n                        <a href=\"http://www.w3.org/TR/CSS21/cascade.html#value-def-inherit\">inherit</a>\n\n                    </td>\n                    <td>auto</td>\n                    <td>positioned elements</td>\n                    <td>no</td>\n                    <td>&nbsp;</td>\n                    <td>\n                        <a href=\"http://www.w3.org/TR/CSS21/media.html#visual-media-group\">visual</a>\n\n                    </td>\n                </tr>\n            </tbody>\n        </table>\n    </div>\n    <script>\nfunction f(){\n    var cases = {\n        \"event\": {\n            \"msg\": \"会让列号是3倍数的行, 改变背景色, 并让获得它们每一个的上一节点\"\n        }\n\n    }\n}\n\ndefine('{pro}fixture.js', ['{lib}util/chain/chainable.js'], f);\n\n</script>\n</body>\n</html>"
  },
  {
    "path": "src/util/chain/test/playjs.sublime-project",
    "content": "{\n\t\"folders\":\n\t[\n\t\t{\n\t\t\t\"path\": \"/E/code/playjs\"\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "src/util/chain/test/playjs.sublime-workspace",
    "content": "{\n\t\"auto_complete\":\n\t{\n\t\t\"selected_items\":\n\t\t[\n\t\t\t[\n\t\t\t\t\"is\",\n\t\t\t\t\"isCombo\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"Come\",\n\t\t\t\t\"Comment\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"Com\",\n\t\t\t\t\"ContentMeta\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"re\",\n\t\t\t\t\"req\trequire\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"ex\",\n\t\t\t\t\"extracts\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"test\",\n\t\t\t\t\"testDom\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"addLr\",\n\t\t\t\t\"addEventListener\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"_clea\",\n\t\t\t\t\"_cleanEv\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"pro\",\n\t\t\t\t\"proto\tPrototype\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"_cur\",\n\t\t\t\t\"_curnode\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"tpa\",\n\t\t\t\t\"tParsed3\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"class\",\n\t\t\t\t\"className\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"_clas\",\n\t\t\t\t\"_classList\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"_ch\",\n\t\t\t\t\"_checkNodeOneStep\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"clas\",\n\t\t\t\t\"classLists\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"_b\",\n\t\t\t\t\"_byId\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"max-\",\n\t\t\t\t\"max-height\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"get\",\n\t\t\t\t\"getElementById\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"c\",\n\t\t\t\t\"cc\thello\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"mar\",\n\t\t\t\t\"margin-bottom\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"ve\",\n\t\t\t\t\"vendor\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"pa\",\n\t\t\t\t\"padding-top\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"inl\",\n\t\t\t\t\"inline-block\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"pad\",\n\t\t\t\t\"padding\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"padd\",\n\t\t\t\t\"padding-left\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"bac\",\n\t\t\t\t\"background-color\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"ba\",\n\t\t\t\t\"background-color\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"font\",\n\t\t\t\t\"font-size\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"in\",\n\t\t\t\t\"inline-block\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"bor\",\n\t\t\t\t\"border\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"fon\",\n\t\t\t\t\"font-size\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"l\",\n\t\t\t\t\"lorem\tLorem ipsum\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"s\",\n\t\t\t\t\"setName\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"ge\",\n\t\t\t\t\"generatedFile\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"fun\",\n\t\t\t\t\"fun\tFunction\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"tes\",\n\t\t\t\t\"testCase\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"req\",\n\t\t\t\t\"require\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"Mat\",\n\t\t\t\t\"Mat3\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"Ma\",\n\t\t\t\t\"Mat3\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"stati\",\n\t\t\t\t\"staticOnly\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"stat\",\n\t\t\t\t\"staticOnly\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"typ\",\n\t\t\t\t\"TypedArray\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"app\",\n\t\t\t\t\"append\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"sta\",\n\t\t\t\t\"staticOnly\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"go\",\n\t\t\t\t\"glMathBoost\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"cons\",\n\t\t\t\t\"constructor\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"de\",\n\t\t\t\t\"describe\tMocha describe snippet\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"eq\",\n\t\t\t\t\"eql\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"ty\",\n\t\t\t\t\"TypedArray\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"e\",\n\t\t\t\t\"eql\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"proto\",\n\t\t\t\t\"prototype\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"gl\",\n\t\t\t\t\"glMath\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"V\",\n\t\t\t\t\"Vec3API\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"deg\",\n\t\t\t\t\"deg2rad\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"leng\",\n\t\t\t\t\"lengthSq\"\n\t\t\t]\n\t\t]\n\t},\n\t\"buffers\":\n\t[\n\t\t{\n\t\t\t\"file\": \"/E/code/playjs/mcss/lib/tokenizer.js\",\n\t\t\t\"settings\":\n\t\t\t{\n\t\t\t\t\"buffer_size\": 11077,\n\t\t\t\t\"line_ending\": \"Windows\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"file\": \"/E/code/playjs/mcss/lib/parser.js\",\n\t\t\t\"settings\":\n\t\t\t{\n\t\t\t\t\"buffer_size\": 9655,\n\t\t\t\t\"line_ending\": \"Windows\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"file\": \"/D/sublime/Data/Packages/User/Preferences.sublime-settings\",\n\t\t\t\"settings\":\n\t\t\t{\n\t\t\t\t\"buffer_size\": 416,\n\t\t\t\t\"line_ending\": \"Unix\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"file\": \"/E/code/playjs/mcss/test/data/parse.mcss\",\n\t\t\t\"settings\":\n\t\t\t{\n\t\t\t\t\"buffer_size\": 43,\n\t\t\t\t\"line_ending\": \"Windows\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"file\": \"/E/code/playjs/mcss/test/data/simple.mcss\",\n\t\t\t\"settings\":\n\t\t\t{\n\t\t\t\t\"buffer_size\": 8084,\n\t\t\t\t\"line_ending\": \"Windows\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"file\": \"/E/code/playjs/mcss/test/specs/test-tokenizer.js\",\n\t\t\t\"settings\":\n\t\t\t{\n\t\t\t\t\"buffer_size\": 3057,\n\t\t\t\t\"line_ending\": \"Windows\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"file\": \"/E/code/playjs/mcss/test/browser/index.html\",\n\t\t\t\"settings\":\n\t\t\t{\n\t\t\t\t\"buffer_size\": 606,\n\t\t\t\t\"line_ending\": \"Windows\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"file\": \"/E/code/playjs/mcss/lib/browser.js\",\n\t\t\t\"settings\":\n\t\t\t{\n\t\t\t\t\"buffer_size\": 191,\n\t\t\t\t\"line_ending\": \"Windows\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"file\": \"/E/code/playjs/mcss/lib/helper/util.js\",\n\t\t\t\"settings\":\n\t\t\t{\n\t\t\t\t\"buffer_size\": 1741,\n\t\t\t\t\"line_ending\": \"Windows\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"file\": \"/E/code/playjs/mcss/dist/mcss-0.0.1.js\",\n\t\t\t\"settings\":\n\t\t\t{\n\t\t\t\t\"buffer_size\": 35839,\n\t\t\t\t\"line_ending\": \"Unix\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"file\": \"/E/code/playjs/mcss/benchmarks/private/predict.js\",\n\t\t\t\"settings\":\n\t\t\t{\n\t\t\t\t\"buffer_size\": 0,\n\t\t\t\t\"line_ending\": \"Windows\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"file\": \"/E/code/playjs/mcss/lib/node/index.js\",\n\t\t\t\"settings\":\n\t\t\t{\n\t\t\t\t\"buffer_size\": 622,\n\t\t\t\t\"line_ending\": \"Windows\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"contents\": \".avenir,.small-caps-avenir,.post-form-host-ctas button.input,.post-form-bottom-cta span.context-copy,.popup.highlight-popup .highlight-number {\\n    font-family:\\\"Avenir Next W10 Medium\\\",\\\"MuseoSans\\\",'Helvetica Neue',Arial\\n}\\n.avenir-demi {\\n    font-family:\\\"Avenir Next W10 Demi\\\",\\\"MuseoSans\\\",'Helvetica Neue',Arial\\n}\\n.avenir-bold {\\n    font-family:\\\"Avenir Next W10 Bold\\\",\\\"MuseoSans\\\",'Helvetica Neue',Arial\\n}\\n.underliner,.room-header .main ul.bullet-items .bullet-item a {\\n    text-decoration:none;\\n    border-bottom:1px dotted #ccc;\\n    cursor:pointer\\n}\\n.is-desktop .underliner:hover,.is-desktop .room-header .main ul.bullet-items .bullet-item a:hover,.room-header .main ul.bullet-items .bullet-item .is-desktop a:hover {\\n    border-bottom-style:solid\\n}\\n.is-mobile .underliner:active,.is-mobile .room-header .main ul.bullet-items .bullet-item a:active,.room-header .main ul.bullet-items .bullet-item .is-mobile a:active {\\n    border-bottom-style:solid\\n}\\n.underliner-nohover {\\n    text-decoration:none;\\n    border-bottom:1px dotted #ccc;\\n    cursor:pointer\\n}\\n.underline-static {\\n    border-bottom:1px solid #ccc\\n}\\n.small-caps-avenir {\\n    font-size:11px;\\n    font-weight:500;\\n    text-transform:uppercase\\n}\\n.wide-title {\\n    color:#fff;\\n    text-shadow:0 2px 3px rgba(0,0,0,0.1),0 -2px 3px rgba(255,255,255,0.1)\\n}\\n.is-desktop .classic-underline-on-hover:hover {\\n    text-decoration:underline\\n}\\n.is-desktop .underline-on-hover:hover {\\n    border-bottom:1px dotted #d2cfc9\\n}\\n@media (max-width:600px) {\\n    .container-mobile-expand {\\n    padding-left:0 !important;\\n    padding-right:0 !important\\n}\\n}i,.icon-before:before,.icon-after:after {\\n    font-family:'Branch';\\n    font-style:normal\\n}\\ni {\\n    font-size:16px\\n}\\n.box {\\n    -webkit-border-radius:5px;\\n    -moz-border-radius:5px;\\n    -ms-border-radius:5px;\\n    -o-border-radius:5px;\\n    border-radius:5px;\\n    -webkit-box-shadow:0px 1px 3px rgba(0,0,0,0.05);\\n    -moz-box-shadow:0px 1px 3px rgba(0,0,0,0.05);\\n    -ms-box-shadow:0px 1px 3px rgba(0,0,0,0.05);\\n    -o-box-shadow:0px 1px 3px rgba(0,0,0,0.05);\\n    box-shadow:0px 1px 3px rgba(0,0,0,0.05);\\n    background:#fff;\\n    border:1px solid #ccc;\\n    border-color:#ebeae5 #e0dfdc #dbdad7\\n}\\n.box-dark {\\n    -webkit-border-radius:5px;\\n    -moz-border-radius:5px;\\n    -ms-border-radius:5px;\\n    -o-border-radius:5px;\\n    border-radius:5px;\\n    border:1px solid #d2cfc9;\\n    -webkit-box-shadow:1px 1px 1px 0 #fff;\\n    -moz-box-shadow:1px 1px 1px 0 #fff;\\n    -ms-box-shadow:1px 1px 1px 0 #fff;\\n    -o-box-shadow:1px 1px 1px 0 #fff;\\n    box-shadow:1px 1px 1px 0 #fff;\\n    background-color:#f2f0eb\\n}\\n.posts-line,.room-header .main,.room-header .top-highlights-container,.posts {\\n    clear:both;\\n    background:url(//d3sipcemvmkij2.cloudfront.net/assets/ui/timeline-9bff3840c33b8fba159a3c03832bc113.png) repeat-y 41px 0\\n}\\n@media (max-width:600px) {\\n    .branch-com .posts-line,.branch-com .room-header .main,.room-header .branch-com .main,.branch-com .room-header .top-highlights-container,.room-header .branch-com .top-highlights-container,.branch-com .posts {\\n    background-position:23px 0\\n}\\n}.white-soft {\\n    text-shadow:rgba(0,0,0,0.1) 0 -1px 3px;\\n    color:white\\n}\\n.grey-icon-on-white {\\n    color:#efede8;\\n    text-shadow:rgba(0,0,0,0.2) -1px -1px 0px\\n}\\n.sprite-image,.popup.highlight-popup .highlight-number .arrow,.top-highlights .arrow {\\n    background-image:url(//d3sipcemvmkij2.cloudfront.net/assets/ui/sprite-af853a3a5bbadf56199662ea7c14c1d4.png)\\n}\\n@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min--moz-device-pixel-ratio:1.5),only screen and (min-resolution:240dpi) {\\n    .sprite-image,.popup.highlight-popup .highlight-number .arrow,.top-highlights .arrow {\\n    background-image:url(//d3sipcemvmkij2.cloudfront.net/assets/ui/sprite@2x-b874d2d3029ec16ae1111514dee9721e.png);\\n    background-size:300px 300px\\n}\\n}.inset {\\n    background:#f2f0eb;\\n    border:1px solid #ebeae5;\\n    -webkit-box-shadow:1px 1px 0 0 #fff;\\n    -moz-box-shadow:1px 1px 0 0 #fff;\\n    -ms-box-shadow:1px 1px 0 0 #fff;\\n    -o-box-shadow:1px 1px 0 0 #fff;\\n    box-shadow:1px 1px 0 0 #fff;\\n    -webkit-border-radius:5px;\\n    -moz-border-radius:5px;\\n    -ms-border-radius:5px;\\n    -o-border-radius:5px;\\n    border-radius:5px\\n}\\n.post.zero-state>.inside .body.post-body i.icon-speech {\\n    color:#f2f0eb;\\n    text-shadow:-1px -1px 1px rgba(0,0,0,0.1),1px 1px 1px #fff\\n}\\n.clear,.box-dark,.posts-line,.room-header .main,.room-header .top-highlights-container,.posts,.container,.room-header,.room-header .topic,.side,.post-form,.post-form-conclusion,.bottom-cta-container,.popup.highlight-popup.bottom .inside,.top-highlights .meta {\\n    zoom:1\\n}\\n.clear:before,.box-dark:before,.posts-line:before,.room-header .main:before,.room-header .top-highlights-container:before,.posts:before,.container:before,.room-header:before,.room-header .topic:before,.side:before,.post-form:before,.post-form-conclusion:before,.bottom-cta-container:before,.popup.highlight-popup.bottom .inside:before,.top-highlights .meta:before,.clear:after,.box-dark:after,.posts-line:after,.room-header .main:after,.room-header .top-highlights-container:after,.posts:after,.container:after,.room-header:after,.room-header .topic:after,.side:after,.post-form:after,.post-form-conclusion:after,.bottom-cta-container:after,.popup.highlight-popup.bottom .inside:after,.top-highlights .meta:after {\\n    content:\\\"\\\";\\n    display:table\\n}\\n.clear:after,.box-dark:after,.posts-line:after,.room-header .main:after,.room-header .top-highlights-container:after,.posts:after,.container:after,.room-header:after,.room-header .topic:after,.side:after,.post-form:after,.post-form-conclusion:after,.bottom-cta-container:after,.popup.highlight-popup.bottom .inside:after,.top-highlights .meta:after {\\n    clear:both\\n}\\n.cover {\\n    position:absolute;\\n    top:0;\\n    left:0;\\n    right:0;\\n    bottom:0;\\n    z-index:10\\n}\\n.border-box-sizing,.popup.highlight-popup .highlight-button .state-container,.popup.highlight-popup .highlight-button .state,.popup.highlight-popup .highlight-number,.top-highlights {\\n    box-sizing:border-box;\\n    -webkit-box-sizing:border-box;\\n    -moz-box-sizing:border-box;\\n    -ms-box-sizing:border-box\\n}\\n@media (min-width:600px) {\\n    body {\\n    min-width:580px\\n}\\n}.container {\\n    width:540px;\\n    margin:0 auto;\\n    position:relative;\\n    padding:0 20px\\n}\\n@media (max-width:600px) {\\n    .container {\\n    width:auto\\n}\\n}body footer,body .room-header .main,body .top-highlights-container,body .floating-side-anchor,body .posts,body .first-post,body .posts-line,body .room-header .main,.room-header body .main,body .room-header .top-highlights-container,.room-header body .top-highlights-container,body .posts,body #post-form,body .conclusion-prompt {\\n    opacity:1;\\n    -webkit-transition:opacity 0.5s;\\n    -moz-transition:opacity 0.5s;\\n    -ms-transition:opacity 0.5s;\\n    -o-transition:opacity 0.5s;\\n    transition:opacity 0.5s\\n}\\nbody.focus-on-add footer,body.focus-on-add .room-header .main,body.focus-on-add .top-highlights-container,body.focus-on-add .floating-side-anchor,body.focus-on-add .posts,body.focus-on-add .first-post,body.focus-on-add .posts-line,body.focus-on-add .room-header .main,.room-header body.focus-on-add .main,body.focus-on-add .room-header .top-highlights-container,.room-header body.focus-on-add .top-highlights-container,body.focus-on-add .posts,body.focus-on-add #post-form,body.focus-on-add .conclusion-prompt {\\n    opacity:.2\\n}\\n.branch-com .master-container {\\n    padding-bottom:20px\\n}\\n.room-header {\\n    width:540px;\\n    position:relative\\n}\\n@media (max-width:600px) {\\n    .room-header {\\n    width:auto\\n}\\n}.room-header .main {\\n    padding:0 20px 10px;\\n    position:relative\\n}\\n.room-header .main.link {\\n    cursor:default\\n}\\n.room-header .roster {\\n    margin:0 0 23px\\n}\\n@media (max-width:600px) {\\n    .room-header .roster {\\n    margin:0 0 15px;\\n    padding-top:0;\\n    padding-bottom:10px\\n}\\n}.room-header .roster .over-capacity-popup {\\n    left:50%;\\n    margin-left:-100px;\\n    width:200px\\n}\\n.room-header .roster span.is-talking-with {\\n    display:inline-block\\n}\\n.room-header .roster span.is-talking-with,.room-header .roster .person,.room-header .roster .function {\\n    height:27px;\\n    margin-bottom:3px\\n}\\n.room-header .roster .person.new-pending {\\n    height:auto\\n}\\n.room-header #room-actions {\\n    z-index:1\\n}\\n.room-header .avatar.host {\\n    float:left;\\n    width:48px;\\n    height:48px;\\n    margin-left:-2px;\\n    margin-bottom:10px\\n}\\n.room-header h2 {\\n    font-size:28px;\\n    line-height:1.3;\\n    margin:0px\\n}\\n@media (max-width:600px) {\\n    .room-header h2 {\\n    font-size:23px;\\n    margin-top:2px;\\n    line-height:28px\\n}\\n}.room-header h2.long-title {\\n    font-size:23px\\n}\\n.room-header h2 a {\\n    color:#444\\n}\\n.room-header .topic {\\n    margin-left:64px;\\n    margin-bottom:10px;\\n    word-wrap:break-word\\n}\\n.room-header .posted-in {\\n    margin-top:10px\\n}\\n.room-header .posted-in .branch-card {\\n    display:inline-block;\\n    margin:0 0 0 5px;\\n    width:auto;\\n    float:none\\n}\\n.room-header .posted-in .branch-card .branch {\\n    padding:5px 5px 3px;\\n    height:auto;\\n    -webkit-border-radius:0;\\n    -moz-border-radius:0;\\n    -ms-border-radius:0;\\n    -o-border-radius:0;\\n    border-radius:0\\n}\\n.room-header .posted-in {\\n    display:inline-block;\\n    margin-top:0\\n}\\n.room-header .posted-in .branch-card {\\n    margin:-5px 20px 5px -5px\\n}\\n@media (max-width:600px) {\\n    .branch-com .room-header .avatar.host {\\n    width:36px;\\n    height:36px;\\n    margin-left:8px\\n}\\n}.floating-side-anchor {\\n    position:absolute;\\n    left:100%;\\n    margin-left:20px;\\n    top:0px\\n}\\n@media (max-width:600px) {\\n    .floating-side-anchor {\\n    display:none\\n}\\n}.side {\\n    width:80px\\n}\\n@media (max-width:600px) {\\n    .side {\\n    width:auto;\\n    margin-bottom:15px\\n}\\n}.side>ul>li+li {\\n    margin-top:10px\\n}\\n@media (max-width:600px) {\\n    .side>ul>li {\\n    margin:0 10px 10px 0;\\n    display:inline-block;\\n    width:auto;\\n    min-width:80px;\\n    vertical-align:top\\n}\\n.side>ul>li+li {\\n    margin-top:0\\n}\\n}.side.detached>ul {\\n    margin:-20px 0 -30px -19px;\\n    padding:20px 0 30px 19px;\\n    background:-webkit-linear-gradient(top,rgba(250,249,244,0.9) 80%,rgba(250,249,244,0));\\n    background:-moz-linear-gradient(top,rgba(250,249,244,0.9) 80%,rgba(250,249,244,0));\\n    background:-ms-linear-gradient(top,rgba(250,249,244,0.9) 80%,rgba(250,249,244,0));\\n    background:-o-linear-gradient(top,rgba(250,249,244,0.9) 80%,rgba(250,249,244,0));\\n    background:linear-gradient(top,rgba(250,249,244,0.9) 80%,rgba(250,249,244,0))\\n}\\n@media (max-width:600px) {\\n    .side.detached {\\n    position:static !important\\n}\\n.side.detached>ul {\\n    margin:0 0 20px;\\n    padding:0\\n}\\n}.side .embed-button,.side .more-info-button,.side .incoming-invite-requests-button,.side .side-button {\\n    width:100%;\\n    padding-left:0;\\n    padding-right:0\\n}\\n.side .incoming-invite-requests-button {\\n    position:relative;\\n    white-space:normal;\\n    padding-left:10px;\\n    padding-right:10px\\n}\\n.embed-popup {\\n    left:50%;\\n    margin-left:-80px;\\n    width:160px\\n}\\n.embed-popup textarea {\\n    margin-top:5px;\\n    height:34px;\\n    white-space:nowrap;\\n    width:100%;\\n    font-size:10px\\n}\\n#post-form .post.over-capacity>.inside {\\n    min-height:0\\n}\\n#post-form .post.over-capacity>.inside .art.grey-icon-on-white i {\\n    font-size:44px;\\n    float:left;\\n    line-height:68px;\\n    padding-left:4px\\n}\\n#post-form .post.over-capacity>.inside .text {\\n    margin-left:60px\\n}\\n#post-form .post.over-capacity>.inside .text h3 {\\n    margin-bottom:0;\\n    padding-top:4px;\\n    font-size:15px\\n}\\n.post-form,.post-form-conclusion {\\n    clear:both;\\n    width:100%\\n}\\n.post-form textarea,.post-form-conclusion textarea {\\n    min-height:58px\\n}\\n@media (max-width:600px) {\\n    .post-form textarea,.post-form-conclusion textarea {\\n    min-height:120px\\n}\\n}.post-form .main-input+.placeholder,.post-form-conclusion .main-input+.placeholder {\\n    font-size:14px\\n}\\n.post-form .postform-error-popup,.post-form-conclusion .postform-error-popup {\\n    min-height:0;\\n    left:50%;\\n    margin-left:-75px;\\n    width:150px\\n}\\n.post-form .tips,.post-form-conclusion .tips {\\n    width:200px;\\n    margin-left:34px;\\n    font-size:11px\\n}\\n.post-form .tips ul.list li,.post-form-conclusion .tips ul.list li {\\n    margin:2px 0\\n}\\n.post-form .tips h4,.post-form-conclusion .tips h4 {\\n    display:block;\\n    margin-bottom:0px\\n}\\n@media (max-width:600px) {\\n    .post-form .tips,.post-form-conclusion .tips {\\n    display:none\\n}\\n}@media (max-width:700px) {\\n    .post-form .tips-container,.post-form-conclusion .tips-container {\\n    display:none\\n}\\n}.post-form .edit-tweet,.post-form-conclusion .edit-tweet {\\n    font-size:11px;\\n    margin-left:5px\\n}\\n.post-form .share-text-popup,.post-form-conclusion .share-text-popup {\\n    left:50%;\\n    margin-left:-125px;\\n    width:250px;\\n    font-size:11px;\\n    margin-bottom:20px\\n}\\n.post-form .share-text-popup .inside,.post-form-conclusion .share-text-popup .inside {\\n    padding-bottom:5px\\n}\\n.post-form .share-text-popup textarea,.post-form-conclusion .share-text-popup textarea {\\n    min-height:80px\\n}\\n.post-form .share-text-popup .link-preview,.post-form-conclusion .share-text-popup .link-preview {\\n    color:#b5b3b0;\\n    text-align:left\\n}\\n.post-form>.avatar,.post-form-conclusion>.avatar {\\n    float:left\\n}\\n.post-form>.avatar.avatar-pending,.post-form-conclusion>.avatar.avatar-pending {\\n    width:48px;\\n    height:48px;\\n    font-size:48px\\n}\\n@media (max-width:600px) {\\n    .post-form>.avatar,.post-form-conclusion>.avatar {\\n    display:none !important\\n}\\n}.post-form>.content,.post-form-conclusion>.content {\\n    margin-left:60px\\n}\\n@media (max-width:600px) {\\n    .post-form>.content,.post-form-conclusion>.content {\\n    margin-left:0\\n}\\n}.post .body .post-form .attachments {\\n    margin-top:5px\\n}\\n.post .body .post-form .attachments .icon-x {\\n    margin-left:2px;\\n    vertical-align:1px\\n}\\n.post-form-conclusion {\\n    display:none;\\n    opacity:0\\n}\\n.conclusion-prompt {\\n    font-size:11px;\\n    color:#6b635b;\\n    margin-left:17px;\\n    margin-top:10px\\n}\\n.post-form-host-ctas button.button.large {\\n    position:relative\\n}\\n.post-form-host-ctas button.button.large i.icon-plus {\\n    position:absolute;\\n    left:10px;\\n    top:10px;\\n    font-size:11px\\n}\\n.post-form-host-ctas button.input {\\n    font-size:15px;\\n    color:#9a948d;\\n    width:340px;\\n    text-align:left;\\n    padding-top:9px;\\n    padding-bottom:9px\\n}\\n.post-form-host-ctas button.input:hover {\\n    cursor:text\\n}\\n@media (max-width:600px) {\\n    .post-form-host-ctas button.input {\\n    margin-top:10px;\\n    width:100%\\n}\\n}.post-form-bottom-cta {\\n    background:#f2f0eb;\\n    -webkit-border-radius:0 0 5px 5px;\\n    -moz-border-radius:0 0 5px 5px;\\n    -ms-border-radius:0 0 5px 5px;\\n    -o-border-radius:0 0 5px 5px;\\n    border-radius:0 0 5px 5px;\\n    border-top:1px solid #d2cfc9;\\n    margin:15px -17px -19px;\\n    padding:8px 19px 10px;\\n    text-align:center\\n}\\n.post-form-bottom-cta .twitter-share-button {\\n    vertical-align:-5px;\\n    margin-right:3px\\n}\\n.post-form-bottom-cta img {\\n    vertical-align:top\\n}\\n.post-form-bottom-cta span.context-copy {\\n    color:#9a948d;\\n    line-height:20px\\n}\\n.post-form-bottom-cta .bring-someone-button {\\n    vertical-align:1px;\\n    margin-left:3px\\n}\\n#post-form .post .inside {\\n    border-radius:5px\\n}\\n.bottom-cta-container {\\n    overflow:hidden;\\n    width:540px;\\n    background-image:url(data:image/png;\\n    base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADIAQMAAAATPBm2AAAAA3NCSVQICAjb4U/gAAAABlBMVEXn5uH///9nz6DFAAAAAnRSTlP/AOW3MEoAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAUdEVYdENyZWF0aW9uIFRpbWUAOC84LzEyCKxbvAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNXG14zYAAAAOSURBVBiVY2AYBYMJAAABkAAB2POVPwAAAABJRU5ErkJggg==);\\n    background-repeat:no-repeat;\\n    background-position:41px -157px;\\n    padding-top:25px;\\n    padding-bottom:10px\\n}\\n@media (max-width:600px) {\\n    .bottom-cta-container {\\n    width:auto\\n}\\n}.bottom-cta-container.has-next {\\n    background-position:41px 0\\n}\\n@media (max-width:600px) {\\n    .bottom-cta-container.has-next {\\n    background-position:22px 0\\n}\\n}.bottom-cta-container .cta-art .node,.bottom-cta-container .cta-art .pulsing-node {\\n    width:36px;\\n    height:36px;\\n    -webkit-border-radius:18px;\\n    -moz-border-radius:18px;\\n    -ms-border-radius:18px;\\n    -o-border-radius:18px;\\n    border-radius:18px;\\n    -webkit-transition:background 0.3s;\\n    -moz-transition:background 0.3s;\\n    -ms-transition:background 0.3s;\\n    -o-transition:background 0.3s;\\n    transition:background 0.3s;\\n    margin-left:23px;\\n    position:absolute\\n}\\n.bottom-cta-container .cta-art .node,.bottom-cta-container .cta-art .pulsing-node {\\n    border:1px solid rgba(156,5,0,0.6);\\n    background-color:rgba(156,5,0,0.6)\\n}\\n.bottom-cta-container .cta-art .node.empty-node,.bottom-cta-container .cta-art .pulsing-node {\\n    border:1px solid rgba(0,0,0,0.08);\\n    background:none\\n}\\n.bottom-cta-container .cta-art .node .node-nucleus {\\n    width:4px;\\n    height:4px;\\n    background-color:black;\\n    -webkit-border-radius:2px;\\n    -moz-border-radius:2px;\\n    -ms-border-radius:2px;\\n    -o-border-radius:2px;\\n    border-radius:2px;\\n    margin:16px 0 0 16px\\n}\\n.bottom-cta-container .cta-art .pulsing-node {\\n    -webkit-animation:pulsate 3s ease-out infinite;\\n    -moz-animation:pulsate 3s ease-out infinite;\\n    -ms-animation:pulsate 3s ease-out infinite;\\n    -o-animation:pulsate 3s ease-out infinite;\\n    animation:pulsate 3s ease-out infinite\\n}\\n.bottom-cta-container .cta-art .animation-container {\\n    position:absolute\\n}\\n.bottom-cta-container .cta-art .animation-container .node,.bottom-cta-container .cta-art .animation-container .pulsing-node {\\n    position:relative;\\n    z-index:100\\n}\\n.bottom-cta-container .text {\\n    margin-left:80px;\\n    width:270px;\\n    float:left\\n}\\n.bottom-cta-container .text h2 {\\n    margin-top:-4px;\\n    font-size:22px;\\n    margin-bottom:0;\\n    color:#4b4a49\\n}\\n@media (max-width:600px) {\\n    .bottom-cta-container .text h2 {\\n    font-size:17px\\n}\\n}.bottom-cta-container .text p {\\n    font-size:13px;\\n    color:#989694;\\n    margin-bottom:10px\\n}\\n.bottom-cta-container .ctas {\\n    width:160px;\\n    padding-top:5px;\\n    margin-right:20px;\\n    float:right;\\n    text-align:right\\n}\\n.bottom-cta-container .ctas>.button {\\n    margin-bottom:10px;\\n    width:100px\\n}\\n.bottom-cta-container+.bottom-cta-container {\\n    border-top:1px solid rgba(0,0,0,0.08);\\n    padding-top:20px\\n}\\n.bottom-cta-container.concluded .text {\\n    width:auto;\\n    padding-bottom:20px\\n}\\n.bottom-cta-container.concluded .node {\\n    margin-top:10px;\\n    text-align:center\\n}\\n.bottom-cta-container.concluded .node .icon-check {\\n    position:absolute;\\n    left:50%;\\n    top:50%;\\n    margin-top:-8px;\\n    margin-left:-8px;\\n    width:16px;\\n    height:16px;\\n    line-height:1;\\n    color:white;\\n    z-index:10\\n}\\n@media (max-width:600px) {\\n    .bottom-cta-container {\\n    background-position:22px -153px;\\n    padding-top:10px\\n}\\n.bottom-cta-container .text,.bottom-cta-container.concluded .text {\\n    width:auto;\\n    margin-right:20px;\\n    padding-bottom:0;\\n    padding-top:6px\\n}\\n.bottom-cta-container .text h2,.bottom-cta-container.concluded .text h2 {\\n    font-size:17px\\n}\\n.bottom-cta-container.concluded .text {\\n    padding-top:12px\\n}\\n.bottom-cta-container .ctas {\\n    float:none;\\n    clear:both;\\n    margin-left:80px;\\n    width:auto;\\n    text-align:left\\n}\\n.bottom-cta-container .text,.bottom-cta-container.concluded .text,.bottom-cta-container .ctas {\\n    margin-left:55px\\n}\\n.bottom-cta-container .cta-art .node {\\n    margin-left:7px;\\n    margin-top:20px;\\n    width:30px;\\n    height:30px;\\n    -webkit-border-radius:15px;\\n    -moz-border-radius:15px;\\n    -ms-border-radius:15px;\\n    -o-border-radius:15px;\\n    border-radius:15px\\n}\\n.bottom-cta-container .cta-art .node .node-nucleus {\\n    margin:13px 0 0 13px\\n}\\n.bottom-cta-container .cta-art .pulsing-node {\\n    display:none\\n}\\n}@media (max-width:600px) {\\n    .branch-embedded .bottom-cta-container.concluded {\\n    padding-bottom:20px\\n}\\n.branch-embedded .bottom-cta-container.concluded .text {\\n    padding-top:22px\\n}\\n}.show-new-posts-alert.new-posts-alert {\\n    height:50px\\n}\\n.show-new-posts-alert .stacked-buttons li.new-posts-alert-button {\\n    display:inline-block\\n}\\n.show-new-posts-alert .stacked-buttons li.regular-post-button {\\n    display:none\\n}\\n.stacked-buttons li.new-posts-alert-button {\\n    display:none\\n}\\n.fade-in,.post-right-side .side-title,.branches h4,.branches .html-arrow,.branches .branch-this-container .icon-help {\\n    opacity:0;\\n    -webkit-transition:opacity 0.15s;\\n    -moz-transition:opacity 0.15s;\\n    -ms-transition:opacity 0.15s;\\n    -o-transition:opacity 0.15s;\\n    transition:opacity 0.15s\\n}\\nbody,#all-container {\\n    background-repeat:no-repeat;\\n    background-position:50% -10px\\n}\\nbody {\\n    background-image:url(//d3sipcemvmkij2.cloudfront.net/assets/ui/timeline-vertical-92641754f1763c5cd57e9f7a6ef5dc90.png)\\n}\\n#all-container {\\n    background-image:url(//d3sipcemvmkij2.cloudfront.net/assets/ui/vline-10p-5a730ce2d42b199ea6246befc238024f.png)\\n}\\n.post-right-side {\\n    position:absolute;\\n    top:37px;\\n    left:100%;\\n    bottom:12px\\n}\\n@media (max-width:600px) {\\n    .post-right-side {\\n    display:none\\n}\\n}.branches {\\n    display:none;\\n    position:absolute;\\n    left:0;\\n    bottom:0;\\n    white-space:nowrap;\\n    color:#6b635b;\\n    font-size:11px\\n}\\n.branches h4 {\\n    margin-bottom:0;\\n    margin-left:8px\\n}\\n.branches .branch-link {\\n    font-size:0;\\n    display:inline-block;\\n    padding:3px 3px 3px 7px;\\n    cursor:pointer;\\n    background:url(//d3sipcemvmkij2.cloudfront.net/assets/ui/vline-10p-5a730ce2d42b199ea6246befc238024f.png) no-repeat -1193px 50%\\n}\\n.branches .branch-link>span {\\n    font-size:11px\\n}\\n.branches .branch-bg {\\n    display:inline-block;\\n    background:#faf9f4\\n}\\n.branches .avatar {\\n    -webkit-transition:opacity 0.15s;\\n    -moz-transition:opacity 0.15s;\\n    -ms-transition:opacity 0.15s;\\n    -o-transition:opacity 0.15s;\\n    transition:opacity 0.15s;\\n    opacity:0.5\\n}\\n.branches .branch-owner {\\n    display:inline-block;\\n    padding-left:2px;\\n    -webkit-transition:opacity 0.15s;\\n    -moz-transition:opacity 0.15s;\\n    -ms-transition:opacity 0.15s;\\n    -o-transition:opacity 0.15s;\\n    transition:opacity 0.15s;\\n    opacity:0.5\\n}\\n.branches .branch-this-copy {\\n    -webkit-transition:opacity 0.15s;\\n    -moz-transition:opacity 0.15s;\\n    -ms-transition:opacity 0.15s;\\n    -o-transition:opacity 0.15s;\\n    transition:opacity 0.15s;\\n    opacity:0\\n}\\n.branches .hidden-branches {\\n    display:none\\n}\\n.branches .reveal-branches {\\n    display:none;\\n    margin-top:3px;\\n    font-size:11px;\\n    color:#6b635b;\\n    cursor:pointer;\\n    margin-left:1px\\n}\\n.branches .reveal-branches .branch-bg {\\n    padding-left:6px\\n}\\n.branches .reveal-branches .reveal-box {\\n    width:14px;\\n    height:14px;\\n    vertical-align:-1px;\\n    display:inline-block;\\n    border:1px solid #e7e6e3;\\n    color:#e7e6e3;\\n    background:#fff;\\n    text-align:center;\\n    -webkit-border-radius:3px;\\n    -moz-border-radius:3px;\\n    -ms-border-radius:3px;\\n    -o-border-radius:3px;\\n    border-radius:3px;\\n    -webkit-transition-property:color,background;\\n    -moz-transition-property:color,background;\\n    -ms-transition-property:color,background;\\n    -o-transition-property:color,background;\\n    transition-property:color background;\\n    -webkit-transition-duration:0.15s;\\n    -moz-transition-duration:0.15s;\\n    -ms-transition-duration:0.15s;\\n    -o-transition-duration:0.15s;\\n    transition-duration:0.15s\\n}\\n.branches .reveal-branches .reveal-box .plus {\\n    display:block;\\n    font-size:15px;\\n    line-height:13px;\\n    font-weight:bold\\n}\\n.branches .reveal-branches:hover .show-more-box {\\n    border-color:#b5b3b0;\\n    color:#b5b3b0\\n}\\n.branches .reveal-branches .show-less-copy {\\n    display:none\\n}\\n.branches .branch-this-container {\\n    font-size:0\\n}\\n.branches .branch-this-container .branch-this-drawer {\\n    display:inline-block;\\n    border:1px solid #dedcd7;\\n    padding:1px 1px 3px 3px;\\n    margin-left:-1px;\\n    -webkit-border-radius:3px;\\n    -moz-border-radius:3px;\\n    -ms-border-radius:3px;\\n    -o-border-radius:3px;\\n    border-radius:3px;\\n    background:#fcfcf9;\\n    -webkit-transition:all 0.15s;\\n    -moz-transition:all 0.15s;\\n    -ms-transition:all 0.15s;\\n    -o-transition:all 0.15s;\\n    transition:all 0.15s;\\n    vertical-align:-1px\\n}\\n.branches .branch-this-container .branch-this-drawer i {\\n    display:inline-block;\\n    line-height:12px;\\n    color:#9a948d\\n}\\n.branches .branch-this-container .branch-this-copy {\\n    font-size:11px;\\n    vertical-align:1px;\\n    margin-left:2px\\n}\\n.branches .branch-this-container .icon-help {\\n    position:relative;\\n    top:1px;\\n    cursor:pointer;\\n    font-size:12px;\\n    margin-left:2px;\\n    color:#b8b4ae\\n}\\n.branches .branch-this-container .icon-help:hover {\\n    color:#4b4a49\\n}\\n.is-desktop .post:hover .branches h4 {\\n    opacity:1\\n}\\n.is-desktop .post:hover .branches .branch-this-copy,.is-desktop .post:hover .branches .branch-owner,.is-desktop .post:hover .branches .avatar {\\n    opacity:1\\n}\\n.is-desktop .post:hover .branches .branch-this-drawer {\\n    color:#b8b4ae;\\n    border-color:#b8b4ae;\\n    background:#fff\\n}\\n.is-desktop .post:hover .branches .branch-this-drawer i {\\n    color:#6b635b\\n}\\n.is-desktop .post:hover .branches .icon-help {\\n    opacity:1\\n}\\n.is-desktop .post .post-right-side:hover .branch-this-copy {\\n    opacity:0.5\\n}\\n.is-desktop .post .branches .branch-link:hover {\\n    cursor:pointer\\n}\\n.is-desktop .post .branches .branch-link:hover .branch-this-copy,.is-desktop .post .branches .branch-link:hover .avatar,.is-desktop .post .branches .branch-link:hover .html-arrow {\\n    opacity:1\\n}\\n.is-desktop .post .branches .branch-link:hover .branch-owner,.is-desktop .post .branches .branch-link:hover .branch-owner>span {\\n    text-decoration:underline\\n}\\n.is-desktop .post .branches .branch-link:hover .pill {\\n    opacity:1\\n}\\n.post.show-all-branches .branches h4 {\\n    opacity:1\\n}\\n.post.show-all-branches .branches .branch-this-copy {\\n    opacity:1\\n}\\n.post.show-all-branches .branches .hidden-branches {\\n    display:block\\n}\\n.post.show-all-branches .branches .show-more-copy {\\n    display:none\\n}\\n.post.show-all-branches .branches .show-less-copy {\\n    display:inline-block\\n}\\n.highlight {\\n    cursor:default\\n}\\n.highlight.highlight-this-active {\\n    background-color:#fffcef;\\n    border-bottom:1px dotted #fc0\\n}\\n@media (min-width:600px) {\\n    .highlight:hover {\\n    background-color:#fffcef;\\n    border-bottom:1px dotted #fc0\\n}\\n}.highlight.highlighted-shown {\\n    border-bottom:1px solid #f5c400\\n}\\n.highlight.highlighted-mine {\\n    background-color:#fff9e0;\\n    border-bottom:1px solid #fc0\\n}\\n.highlight.highlighted-mine.animate {\\n    -webkit-animation:flash-highlight 0.5s ease-out;\\n    -moz-animation:flash-highlight 0.5s ease-out;\\n    -ms-animation:flash-highlight 0.5s ease-out;\\n    -o-animation:flash-highlight 0.5s ease-out;\\n    animation:flash-highlight 0.5s ease-out\\n}\\n.highlight.has-count {\\n    margin-right:8px\\n}\\n.highlight:hover .highlight-count-indicator {\\n    left:5px\\n}\\n@media (min-width:600px) {\\n    .my-post .highlight[data-highlight-count=\\\"0\\\"]:hover {\\n    background-color:white;\\n    border-bottom:none\\n}\\n}.highlight-count-indicator {\\n    display:inline-block;\\n    background:-webkit-linear-gradient(top,#fc0,#cca300);\\n    background:-moz-linear-gradient(top,#fc0,#cca300);\\n    background:-ms-linear-gradient(top,#fc0,#cca300);\\n    background:-o-linear-gradient(top,#fc0,#cca300);\\n    background:linear-gradient(top,#fc0,#cca300);\\n    -webkit-transition:left 0.15s;\\n    -moz-transition:left 0.15s;\\n    -ms-transition:left 0.15s;\\n    -o-transition:left 0.15s;\\n    transition:left 0.15s;\\n    color:#2f2f2e;\\n    font-size:11px;\\n    font-weight:bold;\\n    vertical-align:top;\\n    position:relative;\\n    line-height:16px;\\n    left:0;\\n    margin:1px 0 0 0;\\n    padding:0 3px 0 3px;\\n    border-radius:0 3px 3px 0\\n}\\n.highlight-count-indicator:before {\\n    content:' ';\\n    display:inline-block;\\n    width:0;\\n    height:0;\\n    border:10px solid white;\\n    border-width:8px 5px;\\n    border-right-color:transparent;\\n    vertical-align:top;\\n    margin-left:-4px\\n}\\n.popup.highlight-popup {\\n    width:200px\\n}\\n.popup.highlight-popup>.arrow {\\n    margin-top:13px\\n}\\n.popup.highlight-popup .highlight-action {\\n    overflow:hidden;\\n    padding:10px;\\n    margin:-10px;\\n    height:27px\\n}\\n.popup.highlight-popup .highlight-button {\\n    width:136px;\\n    height:27px;\\n    -webkit-transition:width 0.15s;\\n    -moz-transition:width 0.15s;\\n    -ms-transition:width 0.15s;\\n    -o-transition:width 0.15s;\\n    transition:width 0.15s;\\n    position:relative;\\n    cursor:default\\n}\\n.popup.highlight-popup .highlight-button .state-container {\\n    padding:0;\\n    overflow:hidden;\\n    width:100%;\\n    height:100%;\\n    cursor:pointer\\n}\\n.popup.highlight-popup .highlight-button i.icon-check {\\n    color:#fc0;\\n    font-size:16px;\\n    line-height:14px;\\n    vertical-align:-2px\\n}\\n.popup.highlight-popup .highlight-button .state {\\n    width:100%;\\n    height:100%;\\n    padding-top:5px;\\n    -webkit-transition:margin 0.15s;\\n    -moz-transition:margin 0.15s;\\n    -ms-transition:margin 0.15s;\\n    -o-transition:margin 0.15s;\\n    transition:margin 0.15s\\n}\\n.popup.highlight-popup .highlight-number {\\n    border:1px solid #d2cfc9;\\n    -webkit-border-radius:3px;\\n    -moz-border-radius:3px;\\n    -ms-border-radius:3px;\\n    -o-border-radius:3px;\\n    border-radius:3px;\\n    display:inline-block;\\n    width:35px;\\n    height:27px;\\n    line-height:25px;\\n    text-align:center;\\n    position:absolute;\\n    margin-left:10px;\\n    left:100%;\\n    top:-1px\\n}\\n.popup.highlight-popup .highlight-number .arrow {\\n    position:absolute;\\n    margin:0;\\n    top:50%;\\n    margin-top:-4px;\\n    left:-5px;\\n    right:100%;\\n    width:5px;\\n    height:8px;\\n    background-position:-97px -67px\\n}\\n.popup.highlight-popup .highlighted-by {\\n    display:none\\n}\\n.popup.highlight-popup .highlighted-by h4 {\\n    margin-bottom:3px\\n}\\n.popup.highlight-popup .highlighter-images {\\n    line-height:20px;\\n    font-size:11px;\\n    margin-bottom:4px\\n}\\n.popup.highlight-popup .highlighter-images .avatar {\\n    width:27px;\\n    height:27px;\\n    margin-bottom:5px\\n}\\n.popup.highlight-popup .branching-form textarea {\\n    min-height:40px;\\n    max-height:200px\\n}\\n@media (min-device-width:768px) and (max-device-width:1024px) {\\n    .popup.highlight-popup .branching-form textarea {\\n    min-height:100px\\n}\\n}.popup.highlight-popup .branching-form .send-cta li {\\n    margin-right:5px\\n}\\n.popup.highlight-popup .branching-form .send-cta li.primary {\\n    margin-left:0;\\n    margin-right:0\\n}\\n.popup.highlight-popup .branching-form .send-cta input.checkbox {\\n    vertical-align:1px\\n}\\n.popup.highlight-popup .share-container {\\n    overflow:hidden;\\n    -webkit-transition-property:height,opacity;\\n    -moz-transition-property:height,opacity;\\n    -ms-transition-property:height,opacity;\\n    -o-transition-property:height,opacity;\\n    transition-property:height opacity;\\n    -webkit-transition-duration:0.15s;\\n    -moz-transition-duration:0.15s;\\n    -ms-transition-duration:0.15s;\\n    -o-transition-duration:0.15s;\\n    transition-duration:0.15s;\\n    -webkit-transition-delay:0.5s;\\n    -moz-transition-delay:0.5s;\\n    -ms-transition-delay:0.5s;\\n    -o-transition-delay:0.5s;\\n    transition-delay:0.5s;\\n    height:0;\\n    opacity:0\\n}\\n.popup.highlight-popup .share {\\n    margin-top:8px;\\n    padding:6px;\\n    -webkit-box-shadow:0 1px 2px rgba(0,0,0,0.1) inset;\\n    -moz-box-shadow:0 1px 2px rgba(0,0,0,0.1) inset;\\n    -ms-box-shadow:0 1px 2px rgba(0,0,0,0.1) inset;\\n    -o-box-shadow:0 1px 2px rgba(0,0,0,0.1) inset;\\n    box-shadow:0 1px 2px rgba(0,0,0,0.1) inset;\\n    border:1px solid #dedcd7\\n}\\n.popup.highlight-popup .share li {\\n    display:inline-block;\\n    margin:0\\n}\\n.popup.highlight-popup .share li.link {\\n    margin-left:10px;\\n    margin-top:3px\\n}\\n.popup.highlight-popup .share li.twitter {\\n    margin-right:3px\\n}\\n.popup.highlight-popup .share .icon-link {\\n    font-size:12px;\\n    color:#9a948d\\n}\\n.popup.highlight-popup .share .input.xnaked {\\n    margin-left:-2px;\\n    width:78px;\\n    font-size:11px;\\n    line-height:1;\\n    color:#9a948d;\\n    vertical-align:1px\\n}\\n.popup.highlight-popup.my-post.no-highlights .highlighted-by {\\n    display:none\\n}\\n.popup.highlight-popup.my-post .highlighted-by {\\n    display:block\\n}\\n.popup.highlight-popup.my-post .share-container {\\n    opacity:1;\\n    height:37px\\n}\\n.popup.highlight-popup.my-post .share {\\n    margin-top:0\\n}\\n.popup.highlight-popup.my-post .highlight-action,.popup.highlight-popup.my-post .send-cta .checkbox {\\n    display:none\\n}\\n.popup.highlight-popup.no-highlights .highlight-button {\\n    width:174px\\n}\\n.popup.highlight-popup.no-highlights .highlight-number {\\n    opacity:0\\n}\\n.popup.highlight-popup.highlighted-shown .state-container {\\n    background-image:none;\\n    background-color:transparent;\\n    border:1px solid #ebeae5;\\n    color:#9a948d\\n}\\n.popup.highlight-popup.highlighted-shown .state-container .off-state {\\n    margin-top:-25px\\n}\\n.popup.highlight-popup.highlighted-shown .share-container {\\n    height:44px;\\n    opacity:1\\n}\\n.popup.highlight-popup.bottom {\\n    bottom:auto;\\n    background-color:rgba(0,0,0,0.8);\\n    -webkit-box-shadow:rgba(0,0,0,0.4) 0 1px 7px;\\n    -moz-box-shadow:rgba(0,0,0,0.4) 0 1px 7px;\\n    -ms-box-shadow:rgba(0,0,0,0.4) 0 1px 7px;\\n    -o-box-shadow:rgba(0,0,0,0.4) 0 1px 7px;\\n    box-shadow:rgba(0,0,0,0.4) 0 1px 7px;\\n    width:230px;\\n    text-align:left\\n}\\n.popup.highlight-popup.bottom .inside {\\n    padding:5px\\n}\\n.popup.highlight-popup.bottom>.arrow {\\n    top:auto;\\n    margin-top:0;\\n    opacity:0.8\\n}\\n.popup.highlight-popup.bottom .branching-form,.popup.highlight-popup.bottom .share-container {\\n    display:none !important\\n}\\n.popup.highlight-popup.bottom .highlight-button {\\n    width:106px;\\n    height:37px;\\n    line-height:18.5px\\n}\\n.popup.highlight-popup.bottom .highlight-number {\\n    -webkit-transition:opacity 0.15s;\\n    -moz-transition:opacity 0.15s;\\n    -ms-transition:opacity 0.15s;\\n    -o-transition:opacity 0.15s;\\n    transition:opacity 0.15s;\\n    height:37px;\\n    line-height:36px;\\n    top:-1px;\\n    margin-left:6px;\\n    width:33px\\n}\\n.popup.highlight-popup.bottom .highlight-number .arrow {\\n    background-position:-146px -117px;\\n    background-color:#323232;\\n    height:7px\\n}\\n.popup.highlight-popup.bottom .state {\\n    padding-top:10px\\n}\\n.popup.highlight-popup.bottom .state-container {\\n    -webkit-box-shadow:none;\\n    -moz-box-shadow:none;\\n    -ms-box-shadow:none;\\n    -o-box-shadow:none;\\n    box-shadow:none\\n}\\n.popup.highlight-popup.bottom.highlighted-shown .off-state {\\n    margin-top:-35px\\n}\\n.popup.highlight-popup.bottom .highlighted-by .highlighter-images {\\n    line-height:28px\\n}\\n.popup.highlight-popup.bottom .highlighted-by .highlighter-images .avatar {\\n    width:24px;\\n    height:24px\\n}\\n.popup.highlight-popup.bottom.no-highlights .highlight-button {\\n    width:144px\\n}\\n.popup.highlight-popup.bottom.highlighted-shown .state-container,.popup.highlight-popup.bottom .highlight-number {\\n    color:#fff;\\n    text-shadow:0 1px 0 #000\\n}\\n.popup.highlight-popup.bottom .highlight-action {\\n    height:37px\\n}\\n.popup.highlight-popup.bottom .twitter-share {\\n    padding-top:10px;\\n    padding-bottom:10px;\\n    position:absolute;\\n    right:36px;\\n    top:4px\\n}\\n.popup.highlight-popup.bottom .mobile-close {\\n    display:inline-block;\\n    position:absolute;\\n    padding:16px 10px;\\n    right:0;\\n    top:0;\\n    font-size:14px;\\n    line-height:1;\\n    border-left:1px solid rgba(255,255,255,0.3);\\n    box-shadow:rgba(0,0,0,0.5) -1px 0 0 0;\\n    text-shadow:black 0 1px 0\\n}\\n.popup.highlight-popup.bottom.my-post {\\n    text-align:center;\\n    min-height:64px\\n}\\n.popup.highlight-popup.bottom.my-post .mobile-close {\\n    padding:5px;\\n    border-left:none;\\n    box-shadow:none\\n}\\n.popup.highlight-popup.bottom.my-post h4 {\\n    color:#b8b4ae\\n}\\n.popup.highlight-popup.bottom.my-post.in-progress {\\n    background-image:url(//d3sipcemvmkij2.cloudfront.net/assets/ui/spinner-48-white-4341e1cad56718581e1045f813897b78.gif);\\n    background-repeat:no-repeat;\\n    background-position:50% 50%;\\n    background-size:24px 24px\\n}\\n.popup.highlight-popup.bottom.my-post .twitter-share {\\n    display:none\\n}\\n.top-highlights-container .top-highlights-trigger {\\n    display:block\\n}\\n.top-highlights-container .top-highlights {\\n    display:none\\n}\\n.top-highlights-container.show-highlights .top-highlights-trigger {\\n    display:none\\n}\\n.top-highlights-container.show-highlights .top-highlights {\\n    display:block\\n}\\n.top-highlights-trigger {\\n    text-align:center;\\n    margin-bottom:15px\\n}\\n.top-highlights-trigger .button.naked span.count {\\n    display:inline-block;\\n    background:-webkit-linear-gradient(top,#fc0,#cca300);\\n    background:-moz-linear-gradient(top,#fc0,#cca300);\\n    background:-ms-linear-gradient(top,#fc0,#cca300);\\n    background:-o-linear-gradient(top,#fc0,#cca300);\\n    background:linear-gradient(top,#fc0,#cca300);\\n    color:#4b4a49;\\n    font-size:13px;\\n    font-weight:bold;\\n    line-height:16px;\\n    margin:0 1px 0 2px;\\n    padding:0 3px;\\n    border-radius:3px\\n}\\n.top-highlights {\\n    padding:16px 20px;\\n    position:relative;\\n    margin-bottom:20px;\\n    border:1px solid #d2cfc9;\\n    border-radius:5px;\\n    background:#faf9f4\\n}\\n@media (max-width:600px) {\\n    .top-highlights {\\n    border-radius:0;\\n    border-left:0;\\n    border-right:0;\\n    padding:16px 17px\\n}\\n}.top-highlights .arrow {\\n    position:absolute;\\n    bottom:100%;\\n    margin-left:3px;\\n    width:37px;\\n    height:12px;\\n    background-position:-102px -97px\\n}\\n@media (max-width:600px) {\\n    .top-highlights .arrow {\\n    margin-left:-16px\\n}\\n}.top-highlights .close {\\n    position:absolute;\\n    top:5px;\\n    right:8px;\\n    color:#b8b4ae\\n}\\n.top-highlights .close:hover {\\n    color:#6b635b;\\n    cursor:pointer\\n}\\n@media (max-width:600px) {\\n    .top-highlights .close {\\n    padding:10px\\n}\\n}.top-highlights h4 {\\n    font-size:13px;\\n    color:#b8b4ae;\\n    margin-bottom:10px\\n}\\n.top-highlights blockquote {\\n    color:#6b635b;\\n    font-size:15px;\\n    line-height:1.4;\\n    margin-bottom:8px\\n}\\n.top-highlights blockquote span {\\n    border-bottom:1px solid #fc0\\n}\\n.top-highlights blockquote span:hover {\\n    background:#fff9e0\\n}\\n.top-highlights li {\\n    clear:both\\n}\\n.top-highlights li+li {\\n    margin-top:1em\\n}\\n.top-highlights .meta {\\n    font-weight:bold;\\n    color:#9a948d\\n}\\n.top-highlights .meta .author {\\n    float:left\\n}\\n.top-highlights .meta .author .avatar {\\n    vertical-align:-3px\\n}\\n.top-highlights .meta .count {\\n    float:right\\n}\\n.top-highlights .meta .count i.icon-pen {\\n    color:#fc0;\\n    font-size:13px\\n}\\n.branch-embedded .top-highlights {\\n    display:none\\n}\\n.source-node {\\n    background-color:#faf9f4;\\n    border:1px solid #d2cfc9;\\n    border-radius:32px;\\n    width:32px;\\n    height:32px;\\n    line-height:32px;\\n    text-align:center;\\n    color:#b8b4ae;\\n    position:absolute;\\n    left:25px\\n}\\n@media (max-width:600px) {\\n    .branch-com .source-node {\\n    left:10px\\n}\\n}.source-node {\\n    -webkit-transition-property:-webkit-transform,opacity;\\n    -moz-transition-property:-moz-transform,opacity;\\n    -ms-transition-property:-ms-transform,opacity;\\n    -o-transition-property:-o-transform,opacity;\\n    transition-property:transform opacity;\\n    -webkit-transition-duration:0.3s;\\n    -moz-transition-duration:0.3s;\\n    -ms-transition-duration:0.3s;\\n    -o-transition-duration:0.3s;\\n    transition-duration:0.3s;\\n    top:0px\\n}\\n.source-node img.avatar.mini {\\n    vertical-align:-3px;\\n    background:none;\\n    -webkit-box-shadow:none;\\n    -moz-box-shadow:none;\\n    -ms-box-shadow:none;\\n    -o-box-shadow:none;\\n    box-shadow:none\\n}\\n.source-node .icon-speech,.source-node .icon-twitter,.source-node .icon-media,.source-node .icon-link {\\n    display:none\\n}\\n.source-node .icon-twitter:before {\\n    font-size:15px\\n}\\n.compose-form.link .source-node .icon-link,.compose-form.tweet .source-node .icon-twitter,.compose-form.audio .source-node .icon-media,.compose-form.video .source-node .icon-media,.compose-form.image .source-node .icon-media,.compose-form.thoughts .source-node .icon-speech,.compose-form.branch .source-node .icon-speech,.main.link .source-node .icon-link,.main.tweet .source-node .icon-twitter,.main.audio .source-node .icon-media,.main.video .source-node .icon-media,.main.image .source-node .icon-media,.main.thoughts .source-node .icon-speech,.main.branch .source-node .icon-speech {\\n    display:block\\n}\\nul.bullet-items .bullet-item {\\n    white-space:nowrap;\\n    position:relative;\\n    font-size:15px;\\n    line-height:1.4em\\n}\\nul.bullet-items .bullet-item.focused .bullet {\\n    background:#fc0\\n}\\nul.bullet-items .bullet-item.invalid,ul.bullet-items .bullet-item.focused.invalid {\\n    border:1px solid red;\\n    -webkit-animation:shake 1.8s linear;\\n    -moz-animation:shake 1.8s linear;\\n    -ms-animation:shake 1.8s linear;\\n    -o-animation:shake 1.8s linear;\\n    animation:shake 1.8s linear\\n}\\nul.bullet-items .bullet {\\n    position:absolute;\\n    top:16px;\\n    -webkit-border-radius:3px;\\n    -moz-border-radius:3px;\\n    -ms-border-radius:3px;\\n    -o-border-radius:3px;\\n    border-radius:3px;\\n    left:12px;\\n    z-index:10;\\n    -webkit-transition:top 0.15s;\\n    -moz-transition:top 0.15s;\\n    -ms-transition:top 0.15s;\\n    -o-transition:top 0.15s;\\n    transition:top 0.15s;\\n    display:block;\\n    width:5px;\\n    height:5px;\\n    background:#b8b4ae\\n}\\nul.bullet-items .input-bullet {\\n    width:445px;\\n    min-height:38px;\\n    padding:8px 20px 9px 25px;\\n    vertical-align:top;\\n    font-size:15px;\\n    line-height:1.3\\n}\\n@media (max-width:600px) {\\n    ul.bullet-items .input-bullet {\\n    width:100%;\\n    font-size:13px;\\n    line-height:1.3;\\n    padding-right:10px;\\n    min-height:67px\\n}\\n}.compose-form.video .bullet-container,.compose-form.media .bullet-container {\\n    margin-top:20px\\n}\\n.room-header .main .topic {\\n    margin-left:60px\\n}\\n@media (max-width:600px) {\\n    .branch-com .room-header .main .topic {\\n    margin-left:40px\\n}\\n}.room-header .main .bullet-container {\\n    margin:20px 0\\n}\\n@media (max-width:600px) {\\n    .branch-com .room-header .main .bullet-container {\\n    margin:10px 0 10px -20px\\n}\\n}.room-header .main ul.bullet-items {\\n    margin-left:77px;\\n    color:#6b635b\\n}\\n.room-header .main ul.bullet-items li.bullet-item.no-bullet {\\n    margin-left:-17px\\n}\\n.room-header .main ul.bullet-items li.bullet-item.no-bullet .bullet {\\n    display:none\\n}\\n.room-header .main ul.bullet-items .bullet-item {\\n    padding:0 0 10px;\\n    white-space:normal\\n}\\n.room-header .main ul.bullet-items .bullet-item:last-child {\\n    padding-bottom:0\\n}\\n.room-header .main ul.bullet-items .bullet {\\n    top:7px;\\n    left:-15px\\n}\\n@media (max-width:600px) {\\n    .room-header .main .attachments {\\n    margin:0 -20px\\n}\\n.room-header .main .attachments .attachment.tweet .avatar {\\n    margin-left:12px\\n}\\n}.linkify-popup {\\n    min-height:0;\\n    width:200px\\n}\\n.add-bullet {\\n    color:#989694;\\n    margin-top:6px;\\n    margin-left:6px;\\n    font-size:11px;\\n    cursor:pointer\\n}\\n.add-bullet .plus-sign {\\n    width:12px;\\n    height:12px;\\n    padding:0;\\n    border:1px solid #d2cfc9;\\n    vertical-align:-2px;\\n    margin-right:4px;\\n    display:inline-block;\\n    border-radius:3px\\n}\\n.add-bullet .plus-sign:hover {\\n    padding:0\\n}\\n.add-bullet .plus-sign i {\\n    margin:0 -2px;\\n    line-height:12px;\\n    color:#989694\\n}\\n.add-bullet .or-press {\\n    color:#d2cfc9\\n}\\n.unsubscribe-overlay i.icon-email,.unsubscribe-overlay i.icon-group,.membership-revoke-confirmation-overlay i.icon-email,.membership-revoke-confirmation-overlay i.icon-group,.unsubscribe-overlay i.icon-user,.membership-revoke-confirmation-overlay i.icon-user {\\n    line-height:83px;\\n    color:white;\\n    text-shadow:0 -1px 1px rgba(0,0,0,0.1)\\n}\\n.unsubscribe-overlay .for-user,.membership-revoke-confirmation-overlay .for-user {\\n    display:inline-block\\n}\\n.unsubscribe-overlay .for-group,.membership-revoke-confirmation-overlay .for-group {\\n    display:none\\n}\\n.unsubscribe-overlay.removing-group .for-user,.membership-revoke-confirmation-overlay.removing-group .for-user {\\n    display:none\\n}\\n.unsubscribe-overlay.removing-group .for-group,.membership-revoke-confirmation-overlay.removing-group .for-group {\\n    display:inline-block\\n}\\n.unsubscribe-overlay .inside,.membership-revoke-confirmation-overlay .inside {\\n    text-align:center;\\n    max-width:230px\\n}\\n.unsubscribe-overlay i.icon-email,.unsubscribe-overlay i.icon-group,.membership-revoke-confirmation-overlay i.icon-email,.membership-revoke-confirmation-overlay i.icon-group {\\n    margin-top:-20px;\\n    font-size:100px\\n}\\n.unsubscribe-overlay i.icon-user,.membership-revoke-confirmation-overlay i.icon-user {\\n    margin-top:0;\\n    font-size:80px\\n}\\n.unsubscribe-overlay p.pad-above,.membership-revoke-confirmation-overlay p.pad-above {\\n    margin-top:12px\\n}\\n.unsubscribe-overlay .caption,.membership-revoke-confirmation-overlay .caption {\\n    color:#9a948d;\\n    font-size:11px;\\n    max-width:220px\\n}\\n.unsubscribe-overlay .caption.above,.membership-revoke-confirmation-overlay .caption.above {\\n    margin-top:-5px\\n}\\n.unsubscribe-overlay .caption.below,.membership-revoke-confirmation-overlay .caption.below {\\n    margin-top:10px\\n}\\n.unsubscribe-overlay .inside {\\n    text-align:center;\\n    max-width:230px\\n}\\n.unsubscribe-overlay i.icon-email {\\n    margin-top:-20px;\\n    font-size:100px;\\n    line-height:73px;\\n    color:white;\\n    text-shadow:0 -1px 1px rgba(0,0,0,0.1)\\n}\\n.unsubscribe-overlay .caption {\\n    color:#9a948d;\\n    font-size:11px;\\n    max-width:220px;\\n    margin-top:10px\\n}\\n.post.zero-state>.inside {\\n    background-color:#faf9f4;\\n    border-color:rgba(0,0,0,0.1)\\n}\\n.post.zero-state>.inside>.arrow {\\n    background-position:-13px -96px\\n}\\n@media (min-width:600px) {\\n    .post.zero-state>.inside>.arrow.in {\\n    background-position-x:-11px\\n}\\n}.post.zero-state>.inside .body.post-body {\\n    display:block;\\n    text-align:center\\n}\\n.post.zero-state>.inside .body.post-body i.icon-speech {\\n    font-size:80px;\\n    line-height:90px\\n}\\n.post.zero-state>.inside .body.post-body h3 {\\n    margin-bottom:10px;\\n    color:#d2cfc9\\n}\\n@media (max-width:600px) {\\n    .post.zero-state>.inside .body.post-body h3 {\\n    font-size:15px\\n}\\n}\\n\\n.avenir,.small-caps-avenir,.compose-form .input-topic {\\n    font-family:\\\"Avenir Next W10 Medium\\\",\\\"MuseoSans\\\",'Helvetica Neue',Arial\\n}\\n.avenir-demi {\\n    font-family:\\\"Avenir Next W10 Demi\\\",\\\"MuseoSans\\\",'Helvetica Neue',Arial\\n}\\n.avenir-bold {\\n    font-family:\\\"Avenir Next W10 Bold\\\",\\\"MuseoSans\\\",'Helvetica Neue',Arial\\n}\\n.underliner,.room-header .main ul.bullet-items .bullet-item a {\\n    text-decoration:none;\\n    border-bottom:1px dotted #ccc;\\n    cursor:pointer\\n}\\n.is-desktop .underliner:hover,.is-desktop .room-header .main ul.bullet-items .bullet-item a:hover,.room-header .main ul.bullet-items .bullet-item .is-desktop a:hover {\\n    border-bottom-style:solid\\n}\\n.is-mobile .underliner:active,.is-mobile .room-header .main ul.bullet-items .bullet-item a:active,.room-header .main ul.bullet-items .bullet-item .is-mobile a:active {\\n    border-bottom-style:solid\\n}\\n.underliner-nohover {\\n    text-decoration:none;\\n    border-bottom:1px dotted #ccc;\\n    cursor:pointer\\n}\\n.underline-static {\\n    border-bottom:1px solid #ccc\\n}\\n.small-caps-avenir {\\n    font-size:11px;\\n    font-weight:500;\\n    text-transform:uppercase\\n}\\n.wide-title {\\n    color:#fff;\\n    text-shadow:0 2px 3px rgba(0,0,0,0.1),0 -2px 3px rgba(255,255,255,0.1)\\n}\\n.is-desktop .classic-underline-on-hover:hover {\\n    text-decoration:underline\\n}\\n.is-desktop .underline-on-hover:hover {\\n    border-bottom:1px dotted #d2cfc9\\n}\\n@media (max-width:600px) {\\n    .container-mobile-expand {\\n    padding-left:0 !important;\\n    padding-right:0 !important\\n}\\n}i,.icon-before:before,.icon-after:after {\\n    font-family:'Branch';\\n    font-style:normal\\n}\\ni {\\n    font-size:16px\\n}\\n.box {\\n    -webkit-border-radius:5px;\\n    -moz-border-radius:5px;\\n    -ms-border-radius:5px;\\n    -o-border-radius:5px;\\n    border-radius:5px;\\n    -webkit-box-shadow:0px 1px 3px rgba(0,0,0,0.05);\\n    -moz-box-shadow:0px 1px 3px rgba(0,0,0,0.05);\\n    -ms-box-shadow:0px 1px 3px rgba(0,0,0,0.05);\\n    -o-box-shadow:0px 1px 3px rgba(0,0,0,0.05);\\n    box-shadow:0px 1px 3px rgba(0,0,0,0.05);\\n    background:#fff;\\n    border:1px solid #ccc;\\n    border-color:#ebeae5 #e0dfdc #dbdad7\\n}\\n.box-dark {\\n    -webkit-border-radius:5px;\\n    -moz-border-radius:5px;\\n    -ms-border-radius:5px;\\n    -o-border-radius:5px;\\n    border-radius:5px;\\n    border:1px solid #d2cfc9;\\n    -webkit-box-shadow:1px 1px 1px 0 #fff;\\n    -moz-box-shadow:1px 1px 1px 0 #fff;\\n    -ms-box-shadow:1px 1px 1px 0 #fff;\\n    -o-box-shadow:1px 1px 1px 0 #fff;\\n    box-shadow:1px 1px 1px 0 #fff;\\n    background-color:#f2f0eb\\n}\\n.posts-line {\\n    clear:both;\\n    background:url(//d3sipcemvmkij2.cloudfront.net/assets/ui/timeline-9bff3840c33b8fba159a3c03832bc113.png) repeat-y 41px 0\\n}\\n@media (max-width:600px) {\\n    .branch-com .posts-line {\\n    background-position:23px 0\\n}\\n}.white-soft {\\n    text-shadow:rgba(0,0,0,0.1) 0 -1px 3px;\\n    color:white\\n}\\n.grey-icon-on-white {\\n    color:#efede8;\\n    text-shadow:rgba(0,0,0,0.2) -1px -1px 0px\\n}\\n.sprite-image {\\n    background-image:url(//d3sipcemvmkij2.cloudfront.net/assets/ui/sprite-af853a3a5bbadf56199662ea7c14c1d4.png)\\n}\\n@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min--moz-device-pixel-ratio:1.5),only screen and (min-resolution:240dpi) {\\n    .sprite-image {\\n    background-image:url(//d3sipcemvmkij2.cloudfront.net/assets/ui/sprite@2x-b874d2d3029ec16ae1111514dee9721e.png);\\n    background-size:300px 300px\\n}\\n}.inset {\\n    background:#f2f0eb;\\n    border:1px solid #ebeae5;\\n    -webkit-box-shadow:1px 1px 0 0 #fff;\\n    -moz-box-shadow:1px 1px 0 0 #fff;\\n    -ms-box-shadow:1px 1px 0 0 #fff;\\n    -o-box-shadow:1px 1px 0 0 #fff;\\n    box-shadow:1px 1px 0 0 #fff;\\n    -webkit-border-radius:5px;\\n    -moz-border-radius:5px;\\n    -ms-border-radius:5px;\\n    -o-border-radius:5px;\\n    border-radius:5px\\n}\\n.clear,.box-dark,.posts-line,.topic-header-container,.compose-form,.compose-form .next-container,.compose-form .create-container {\\n    zoom:1\\n}\\n.clear:before,.box-dark:before,.posts-line:before,.topic-header-container:before,.compose-form:before,.compose-form .next-container:before,.compose-form .create-container:before,.clear:after,.box-dark:after,.posts-line:after,.topic-header-container:after,.compose-form:after,.compose-form .next-container:after,.compose-form .create-container:after {\\n    content:\\\"\\\";\\n    display:table\\n}\\n.clear:after,.box-dark:after,.posts-line:after,.topic-header-container:after,.compose-form:after,.compose-form .next-container:after,.compose-form .create-container:after {\\n    clear:both\\n}\\n.cover {\\n    position:absolute;\\n    top:0;\\n    left:0;\\n    right:0;\\n    bottom:0;\\n    z-index:10\\n}\\n.border-box-sizing,.topic-header-container,.compose-form .create-container,.compose-form .roster-container .roster.pre-invite-roster {\\n    box-sizing:border-box;\\n    -webkit-box-sizing:border-box;\\n    -moz-box-sizing:border-box;\\n    -ms-box-sizing:border-box\\n}\\n.source-node,.compose-form .timeline-progress {\\n    background-color:#faf9f4;\\n    border:1px solid #d2cfc9;\\n    border-radius:32px;\\n    width:32px;\\n    height:32px;\\n    line-height:32px;\\n    text-align:center;\\n    color:#b8b4ae;\\n    position:absolute;\\n    left:25px\\n}\\n@media (max-width:600px) {\\n    .branch-com .source-node,.branch-com .compose-form .timeline-progress,.compose-form .branch-com .timeline-progress {\\n    left:10px\\n}\\n}.source-node {\\n    -webkit-transition-property:-webkit-transform,opacity;\\n    -moz-transition-property:-moz-transform,opacity;\\n    -ms-transition-property:-ms-transform,opacity;\\n    -o-transition-property:-o-transform,opacity;\\n    transition-property:transform opacity;\\n    -webkit-transition-duration:0.3s;\\n    -moz-transition-duration:0.3s;\\n    -ms-transition-duration:0.3s;\\n    -o-transition-duration:0.3s;\\n    transition-duration:0.3s;\\n    top:0px\\n}\\n.source-node img.avatar.mini {\\n    vertical-align:-3px;\\n    background:none;\\n    -webkit-box-shadow:none;\\n    -moz-box-shadow:none;\\n    -ms-box-shadow:none;\\n    -o-box-shadow:none;\\n    box-shadow:none\\n}\\n.source-node .icon-speech,.source-node .icon-twitter,.source-node .icon-media,.source-node .icon-link {\\n    display:none\\n}\\n.source-node .icon-twitter:before {\\n    font-size:15px\\n}\\n.compose-form.link .source-node .icon-link,.compose-form.tweet .source-node .icon-twitter,.compose-form.audio .source-node .icon-media,.compose-form.video .source-node .icon-media,.compose-form.image .source-node .icon-media,.compose-form.thoughts .source-node .icon-speech,.compose-form.branch .source-node .icon-speech,.main.link .source-node .icon-link,.main.tweet .source-node .icon-twitter,.main.audio .source-node .icon-media,.main.video .source-node .icon-media,.main.image .source-node .icon-media,.main.thoughts .source-node .icon-speech,.main.branch .source-node .icon-speech {\\n    display:block\\n}\\nul.bullet-items .bullet-item {\\n    white-space:nowrap;\\n    position:relative;\\n    font-size:15px;\\n    line-height:1.4em\\n}\\nul.bullet-items .bullet-item.focused .bullet {\\n    background:#fc0\\n}\\nul.bullet-items .bullet-item.invalid,ul.bullet-items .bullet-item.focused.invalid {\\n    border:1px solid red;\\n    -webkit-animation:shake 1.8s linear;\\n    -moz-animation:shake 1.8s linear;\\n    -ms-animation:shake 1.8s linear;\\n    -o-animation:shake 1.8s linear;\\n    animation:shake 1.8s linear\\n}\\nul.bullet-items .bullet {\\n    position:absolute;\\n    top:16px;\\n    -webkit-border-radius:3px;\\n    -moz-border-radius:3px;\\n    -ms-border-radius:3px;\\n    -o-border-radius:3px;\\n    border-radius:3px;\\n    left:12px;\\n    z-index:10;\\n    -webkit-transition:top 0.15s;\\n    -moz-transition:top 0.15s;\\n    -ms-transition:top 0.15s;\\n    -o-transition:top 0.15s;\\n    transition:top 0.15s;\\n    display:block;\\n    width:5px;\\n    height:5px;\\n    background:#b8b4ae\\n}\\nul.bullet-items .input-bullet {\\n    width:445px;\\n    min-height:38px;\\n    padding:8px 20px 9px 25px;\\n    vertical-align:top;\\n    font-size:15px;\\n    line-height:1.3\\n}\\n@media (max-width:600px) {\\n    ul.bullet-items .input-bullet {\\n    width:100%;\\n    font-size:13px;\\n    line-height:1.3;\\n    padding-right:10px;\\n    min-height:67px\\n}\\n}.compose-form.video .bullet-container,.compose-form.media .bullet-container {\\n    margin-top:20px\\n}\\n.room-header .main .topic {\\n    margin-left:60px\\n}\\n@media (max-width:600px) {\\n    .branch-com .room-header .main .topic {\\n    margin-left:40px\\n}\\n}.room-header .main .bullet-container {\\n    margin:20px 0\\n}\\n@media (max-width:600px) {\\n    .branch-com .room-header .main .bullet-container {\\n    margin:10px 0 10px -20px\\n}\\n}.room-header .main ul.bullet-items {\\n    margin-left:77px;\\n    color:#6b635b\\n}\\n.room-header .main ul.bullet-items li.bullet-item.no-bullet {\\n    margin-left:-17px\\n}\\n.room-header .main ul.bullet-items li.bullet-item.no-bullet .bullet {\\n    display:none\\n}\\n.room-header .main ul.bullet-items .bullet-item {\\n    padding:0 0 10px;\\n    white-space:normal\\n}\\n.room-header .main ul.bullet-items .bullet-item:last-child {\\n    padding-bottom:0\\n}\\n.room-header .main ul.bullet-items .bullet {\\n    top:7px;\\n    left:-15px\\n}\\n@media (max-width:600px) {\\n    .room-header .main .attachments {\\n    margin:0 -20px\\n}\\n.room-header .main .attachments .attachment.tweet .avatar {\\n    margin-left:12px\\n}\\n}.linkify-popup {\\n    min-height:0;\\n    width:200px\\n}\\n.add-bullet {\\n    color:#989694;\\n    margin-top:6px;\\n    margin-left:6px;\\n    font-size:11px;\\n    cursor:pointer\\n}\\n.add-bullet .plus-sign {\\n    width:12px;\\n    height:12px;\\n    padding:0;\\n    border:1px solid #d2cfc9;\\n    vertical-align:-2px;\\n    margin-right:4px;\\n    display:inline-block;\\n    border-radius:3px\\n}\\n.add-bullet .plus-sign:hover {\\n    padding:0\\n}\\n.add-bullet .plus-sign i {\\n    margin:0 -2px;\\n    line-height:12px;\\n    color:#989694\\n}\\n.add-bullet .or-press {\\n    color:#d2cfc9\\n}\\n.overlay.twitter-bookmarklet {\\n    background-image:url(//d3sipcemvmkij2.cloudfront.net/assets/twitter-bookmarklet-0cf3732e0eba0819ab2863f9486404ff.png);\\n    width:800px;\\n    margin-left:-440px;\\n    background-repeat:no-repeat;\\n    background-position:0 10px;\\n    padding:40px;\\n    padding-top:40px;\\n    height:400px;\\n    -webkit-font-smoothing:antialiased\\n}\\n.overlay.twitter-bookmarklet.darker-arrow {\\n    background-image:url(//d3sipcemvmkij2.cloudfront.net/assets/twitter-bookmarklet-hover-3ef8f06370840f2ab562c68ad332b569.png)\\n}\\n.overlay.twitter-bookmarklet .background.preload {\\n    background-image:url(//d3sipcemvmkij2.cloudfront.net/assets/twitter-bookmarklet-hover-3ef8f06370840f2ab562c68ad332b569.png)\\n}\\n.overlay.twitter-bookmarklet .close {\\n    top:auto;\\n    bottom:5px\\n}\\n.overlay.twitter-bookmarklet .button.primary.giant-button {\\n    position:absolute;\\n    top:108px;\\n    left:220px;\\n    -webkit-animation:shake 1.8s linear infinite;\\n    -moz-animation:shake 1.8s linear infinite;\\n    -ms-animation:shake 1.8s linear infinite;\\n    -o-animation:shake 1.8s linear infinite;\\n    animation:shake 1.8s linear infinite;\\n    -webkit-transition:all 0.5s;\\n    -moz-transition:all 0.5s;\\n    -ms-transition:all 0.5s;\\n    -o-transition:all 0.5s;\\n    transition:all 0.5s\\n}\\n.overlay.twitter-bookmarklet .button.primary.giant-button:hover,.overlay.twitter-bookmarklet .button.primary.giant-button:active {\\n    cursor:url(//d3sipcemvmkij2.cloudfront.net/assets/grab-502fb80bb5cbe4c4ca6e12f2f20b2e4e.png),default;\\n    top:105px;\\n    left:216px;\\n    -webkit-box-shadow:rgba(0,0,0,0.3) 0 3px 7px;\\n    -moz-box-shadow:rgba(0,0,0,0.3) 0 3px 7px;\\n    -ms-box-shadow:rgba(0,0,0,0.3) 0 3px 7px;\\n    -o-box-shadow:rgba(0,0,0,0.3) 0 3px 7px;\\n    box-shadow:rgba(0,0,0,0.3) 0 3px 7px\\n}\\n.overlay.twitter-bookmarklet .button.primary.giant-button:active {\\n    -webkit-animation:none;\\n    -moz-animation:none;\\n    -ms-animation:none;\\n    -o-animation:none;\\n    animation:none\\n}\\n.overlay.twitter-bookmarklet h1 {\\n    width:420px;\\n    left:50%;\\n    margin-left:-210px;\\n    text-align:center;\\n    margin-bottom:38px;\\n    position:absolute\\n}\\n.overlay.twitter-bookmarklet h1.standard {\\n    display:block\\n}\\n.overlay.twitter-bookmarklet h1.drag-me-up {\\n    display:none\\n}\\n.overlay.twitter-bookmarklet .copy {\\n    width:400px;\\n    float:right;\\n    margin-top:68px\\n}\\n.overlay.twitter-bookmarklet .copy ol li {\\n    font-size:13px;\\n    color:#9a948d;\\n    margin-bottom:60px\\n}\\n.overlay.twitter-bookmarklet .copy ol li h3 {\\n    font-size:17px;\\n    margin-bottom:0\\n}\\n.overlay.twitter-bookmarklet .copy ol li h3 .button.small {\\n    vertical-align:2px\\n}\\n.overlay.twitter-bookmarklet .copy ol li .underliner,.overlay.twitter-bookmarklet .copy ol li .room-header .main ul.bullet-items .bullet-item a,.room-header .main ul.bullet-items .bullet-item .overlay.twitter-bookmarklet .copy ol li a {\\n    color:#6b635b\\n}\\n.overlay.twitter-bookmarklet .copy ol li .underliner:hover,.overlay.twitter-bookmarklet .copy ol li .room-header .main ul.bullet-items .bullet-item a:hover,.room-header .main ul.bullet-items .bullet-item .overlay.twitter-bookmarklet .copy ol li a:hover {\\n    color:#4b4a49\\n}\\n.quick-compose-container {\\n    -webkit-transition:padding 0.3s;\\n    -moz-transition:padding 0.3s;\\n    -ms-transition:padding 0.3s;\\n    -o-transition:padding 0.3s;\\n    transition:padding 0.3s;\\n    padding-top:40px;\\n    padding-bottom:40px\\n}\\n@media (max-width:600px) {\\n    .quick-compose-container {\\n    padding-top:10px;\\n    padding-bottom:10px\\n}\\n}@media (max-width:600px) {\\n    .topic-header-container .people,.roster-container .people {\\n    font-size:13px\\n}\\n}.topic-header-container {\\n    -webkit-transition-property:opacity,margin;\\n    -moz-transition-property:opacity,margin;\\n    -ms-transition-property:opacity,margin;\\n    -o-transition-property:opacity,margin;\\n    transition-property:opacity margin;\\n    -webkit-transition-duration:0.3s;\\n    -moz-transition-duration:0.3s;\\n    -ms-transition-duration:0.3s;\\n    -o-transition-duration:0.3s;\\n    transition-duration:0.3s;\\n    width:540px;\\n    margin:0 auto;\\n    margin-top:18px;\\n    position:relative;\\n    padding-left:74px;\\n    min-height:42px;\\n    opacity:1\\n}\\n@media (max-width:600px) {\\n    .topic-header-container {\\n    width:auto\\n}\\n}.topic-header-container .user-copy {\\n    display:none\\n}\\n.topic-header-container .user-copy .avatar {\\n    width:16px;\\n    height:16px;\\n    vertical-align:-2px\\n}\\n.topic-header-container .user-copy .user-name {\\n    font-size:15px\\n}\\n.topic-header-container .user-copy .remove.icon-x-fat {\\n    color:#d2cfc9;\\n    padding:3px 0;\\n    font-size:15px\\n}\\n.topic-header-container .user-copy .remove.icon-x-fat:hover {\\n    cursor:pointer;\\n    color:#6b635b\\n}\\n@media (min-width:600px) {\\n    .topic-header-container .user-copy span.people {\\n    margin-left:3px;\\n    margin-right:7px;\\n    border:1px solid #d2cfc9;\\n    border-radius:5px;\\n    padding:1px 0;\\n    vertical-align:1px;\\n    background:white\\n}\\n.topic-header-container .user-copy span.people .avatar {\\n    vertical-align:-2px;\\n    margin-left:6px;\\n    width:20px;\\n    height:20px\\n}\\n.topic-header-container .user-copy span.people .user-name {\\n    font-size:17px;\\n    vertical-align:2px\\n}\\n.topic-header-container .user-copy span.people .remove.icon-x-fat {\\n    vertical-align:3px\\n}\\n}.topic-header-container .back-to-profile {\\n    position:absolute;\\n    left:20px;\\n    top:20px;\\n    color:#9a948d;\\n    display:none\\n}\\n.topic-header-container .back-to-profile:hover {\\n    cursor:pointer;\\n    color:#2f2f2e;\\n    border-color:#9a948d\\n}\\n@media (max-width:600px) {\\n    .topic-header-container .back-to-profile {\\n    top:35px;\\n    left:10px;\\n    border:1px solid #d2cfc9;\\n    padding:0 3px;\\n    border-radius:3px\\n}\\n}.topic-header-container.talk-to-user .default-copy {\\n    display:none\\n}\\n.topic-header-container.talk-to-user .user-copy {\\n    display:inline\\n}\\n.topic-header-container.talk-to-user .back-to-profile {\\n    display:block\\n}\\n.topic-header-container.state-1 {\\n    opacity:0\\n}\\n.topic-header-container .topic-header-initial {\\n    -webkit-transition:margin 0.3s;\\n    -moz-transition:margin 0.3s;\\n    -ms-transition:margin 0.3s;\\n    -o-transition:margin 0.3s;\\n    transition:margin 0.3s\\n}\\n.topic-header-container .topic-header-initial h3 {\\n    font-size:23px;\\n    color:#6b635b\\n}\\n@media (max-width:600px) {\\n    .topic-header-container {\\n    margin-top:0;\\n    height:auto;\\n    padding-bottom:8px;\\n    padding-left:64px;\\n    min-height:0\\n}\\n.topic-header-container .topic-header-initial {\\n    height:auto\\n}\\n.topic-header-container .topic-header-initial h3 {\\n    font-size:15px;\\n    line-height:15px\\n}\\n}.compose-form {\\n    width:540px;\\n    margin:0 auto;\\n    position:relative\\n}\\n@media (max-width:600px) {\\n    .compose-form {\\n    width:auto\\n}\\n}.compose-form .source-node,.compose-form .timeline-progress {\\n    left:27px\\n}\\n.compose-form .timeline-container {\\n    margin-right:20px;\\n    float:left;\\n    width:60px;\\n    margin-right:0px;\\n    width:54px;\\n    padding-left:20px;\\n    min-height:60px;\\n    -webkit-transition-property:margin,padding;\\n    -moz-transition-property:margin,padding;\\n    -ms-transition-property:margin,padding;\\n    -o-transition-property:margin,padding;\\n    transition-property:margin padding;\\n    -webkit-transition-duration:0.3s;\\n    -moz-transition-duration:0.3s;\\n    -ms-transition-duration:0.3s;\\n    -o-transition-duration:0.3s;\\n    transition-duration:0.3s\\n}\\n@media (max-width:600px) {\\n    .compose-form .timeline-container {\\n    padding-left:10px\\n}\\n}.compose-form .back-button {\\n    position:absolute;\\n    left:-10px;\\n    top:5px;\\n    font-size:15px;\\n    color:#b8b4ae;\\n    opacity:0;\\n    -webkit-transition:opacity 0.3s;\\n    -moz-transition:opacity 0.3s;\\n    -ms-transition:opacity 0.3s;\\n    -o-transition:opacity 0.3s;\\n    transition:opacity 0.3s\\n}\\n.compose-form .back-button:hover {\\n    color:#4b4a49;\\n    cursor:pointer\\n}\\n@media (max-width:600px) {\\n    .compose-form .back-button {\\n    left:10px\\n}\\n}.compose-form .avatar-container {\\n    position:absolute;\\n    top:0;\\n    left:20px;\\n    -webkit-transition:margin-top 0.3s;\\n    -moz-transition:margin-top 0.3s;\\n    -ms-transition:margin-top 0.3s;\\n    -o-transition:margin-top 0.3s;\\n    transition:margin-top 0.3s\\n}\\n@media (max-width:600px) {\\n    .compose-form .avatar-container {\\n    left:10px\\n}\\n}.compose-form .timeline-progress {\\n    position:absolute;\\n    bottom:0;\\n    line-height:26px\\n}\\n.compose-form .timeline-progress i.icon-user {\\n    position:absolute;\\n    left:8px;\\n    top:2px\\n}\\n.compose-form .form-container {\\n    width:445px;\\n    float:left\\n}\\n@media (max-width:600px) {\\n    .compose-form .form-container {\\n    width:auto;\\n    float:none;\\n    margin-left:64px;\\n    padding-right:10px;\\n    margin-bottom:0px\\n}\\n}.compose-form .has-tooltip .char-count {\\n    opacity:0;\\n    font-weight:bold;\\n    -webkit-transition:opacity 0.15s;\\n    -moz-transition:opacity 0.15s;\\n    -ms-transition:opacity 0.15s;\\n    -o-transition:opacity 0.15s;\\n    transition:opacity 0.15s;\\n    width:80px;\\n    text-align:right\\n}\\n.compose-form .has-tooltip.focused .char-count {\\n    opacity:1\\n}\\n.compose-form .topic-container {\\n    margin-bottom:10px;\\n    margin-top:-5px;\\n    position:relative\\n}\\n.compose-form .topic-container .popup {\\n    width:140px;\\n    top:50%;\\n    margin-top:-26px\\n}\\n.compose-form .input-topic {\\n    font-size:28px;\\n    line-height:1.3;\\n    width:445px;\\n    min-height:49px;\\n    font-weight:500;\\n    padding-right:20px;\\n    padding-top:7px;\\n    -webkit-appearance:none\\n}\\n.compose-form .input-topic.cap-max-width {\\n    max-height:49px\\n}\\n.compose-form .input-topic.invalid {\\n    border:1px solid red;\\n    -webkit-animation:shake 1.8s linear;\\n    -moz-animation:shake 1.8s linear;\\n    -ms-animation:shake 1.8s linear;\\n    -o-animation:shake 1.8s linear;\\n    animation:shake 1.8s linear\\n}\\n@media (max-width:600px) {\\n    .compose-form .input-topic {\\n    width:100%;\\n    font-size:17px;\\n    min-height:36px\\n}\\n}.compose-form .topic-container .char-count,.compose-form .bullet-item .char-count {\\n    position:absolute;\\n    bottom:5px;\\n    right:5px;\\n    margin:0 0 0 4px;\\n    z-index:10\\n}\\n.compose-form .compose-cta {\\n    -webkit-border-radius:3px;\\n    -moz-border-radius:3px;\\n    -ms-border-radius:3px;\\n    -o-border-radius:3px;\\n    border-radius:3px;\\n    font-size:15px;\\n    line-height:1.1em;\\n    padding:7px 10px\\n}\\n.compose-form .next-container,.compose-form .create-container {\\n    -webkit-transition-property:opacity,margin;\\n    -moz-transition-property:opacity,margin;\\n    -ms-transition-property:opacity,margin;\\n    -o-transition-property:opacity,margin;\\n    transition-property:opacity margin;\\n    -webkit-transition-duration:0.3s;\\n    -moz-transition-duration:0.3s;\\n    -ms-transition-duration:0.3s;\\n    -o-transition-duration:0.3s;\\n    transition-duration:0.3s\\n}\\n.compose-form .next-container {\\n    position:relative;\\n    min-height:52px\\n}\\n.compose-form .next-container .button {\\n    position:absolute;\\n    top:0;\\n    right:0\\n}\\n@media (max-width:600px) {\\n    .compose-form .next-container .button {\\n    line-height:15px\\n}\\n}.compose-form .post-container {\\n    -webkit-transition:opacity 0.3s;\\n    -moz-transition:opacity 0.3s;\\n    -ms-transition:opacity 0.3s;\\n    -o-transition:opacity 0.3s;\\n    transition:opacity 0.3s\\n}\\n.compose-form .create-container {\\n    margin-top:15px;\\n    border-top:1px solid rgba(0,0,0,0.07);\\n    padding-top:20px;\\n    padding-left:20px;\\n    margin-left:-75px;\\n    background:#faf9f4;\\n    height:auto\\n}\\n.compose-form .create-container>.stacked-buttons {\\n    float:right\\n}\\n.compose-form .create-container>.stacked-buttons li:first-child {\\n    margin-right:3px\\n}\\n.compose-form .create-container>.stacked-buttons li {\\n    position:relative\\n}\\n.compose-form .create-container>.stacked-buttons span.tweet-label {\\n    margin-right:3px;\\n    vertical-align:2px\\n}\\n.compose-form .create-container>.stacked-buttons .send-to-twitter input.checkbox {\\n    vertical-align:2px\\n}\\n@media (max-width:600px) {\\n    .compose-form .create-container {\\n    text-align:right;\\n    padding-top:10px\\n}\\n.compose-form .create-container .button {\\n    line-height:15px\\n}\\n.compose-form .create-container .send-to-twitter input.checkbox {\\n    vertical-align:0px;\\n    border:1px solid rgba(0,0,0,0.1)\\n}\\n}.compose-form .roster-container {\\n    -webkit-transition:opacity 0.3s;\\n    -moz-transition:opacity 0.3s;\\n    -ms-transition:opacity 0.3s;\\n    -o-transition:opacity 0.3s;\\n    transition:opacity 0.3s;\\n    opacity:0;\\n    position:absolute;\\n    bottom:100%;\\n    left:0;\\n    right:20px\\n}\\n.compose-form .roster-container .roster.pre-invite-roster {\\n    color:#9a948d;\\n    line-height:15px;\\n    margin-bottom:20px;\\n    padding-left:20px;\\n    padding-bottom:15px;\\n    width:100%\\n}\\n@media (max-width:600px) {\\n    .compose-form .roster-container .roster.pre-invite-roster {\\n    margin-bottom:10px;\\n    padding-bottom:11px\\n}\\n}.compose-form .roster-container .roster.pre-invite-roster span.pre-invite-wrap-copy {\\n    display:inline-block;\\n    margin-top:8px\\n}\\n@media (max-width:600px) {\\n    .compose-form .roster-container .roster.pre-invite-roster span.pre-invite-wrap-copy.for-desktop {\\n    display:none\\n}\\n}.compose-form .roster-container .roster.pre-invite-roster span.people {\\n    display:inline-block\\n}\\n.compose-form .roster-container .roster.pre-invite-roster span.people.twitter-invites {\\n    margin-left:5px;\\n    margin-right:-5px\\n}\\n.compose-form .roster-container .roster.pre-invite-roster span.people.twitter-invites span.twitter-person {\\n    display:inline-block;\\n    margin-top:8px\\n}\\n.compose-form .roster-container .roster.pre-invite-roster span.people.twitter-invites span.twitter-person img {\\n    vertical-align:-3px\\n}\\n.compose-form .roster-container .roster.pre-invite-roster span.people.twitter-invites span.twitter-person a.name {\\n    margin-left:1px\\n}\\n@media (max-width:600px) {\\n    .compose-form .roster-container .roster.pre-invite-roster span.people.twitter-invites span.twitter-person a.name {\\n    display:inline-block;\\n    max-width:80px;\\n    overflow:hidden;\\n    text-overflow:ellipsis;\\n    white-space:nowrap\\n}\\n}.compose-form .roster-container .roster.pre-invite-roster span.people.twitter-invites span.twitter-person a.name:hover {\\n    text-decoration:underline\\n}\\n.compose-form .roster-container .roster.pre-invite-roster span.people.twitter-invites span.twitter-person a.remove.icon-x-fat {\\n    color:#d2cfc9;\\n    margin-right:13px;\\n    margin-left:1px;\\n    padding:3px 0\\n}\\n.compose-form .roster-container .roster.pre-invite-roster span.people.twitter-invites span.twitter-person a.remove.icon-x-fat:hover {\\n    color:#6b635b\\n}\\n.compose-form.state-pre-invite .roster-container {\\n    opacity:1\\n}\\n.compose-form.state-pre-invite.for-twitter .roster.pre-invite-roster .twitter-invites,.compose-form.state-pre-invite.for-user .roster.pre-invite-roster .twitter-invites {\\n    display:inline\\n}\\n.compose-form .pre-invite-note {\\n    display:none\\n}\\n.compose-form.state-pre-invite.for-twitter .send-to-twitter {\\n    display:none\\n}\\n.compose-form.state-pre-invite.for-twitter .pre-invite-note {\\n    display:inline-block\\n}\\n.compose-form.state-0 .bullet-container,.compose-form.state-0 .create-container,.compose-form.state-0 .timeline-progress {\\n    display:none\\n}\\n.compose-form.state-0 .roster.pre-invite-roster {\\n    display:none\\n}\\n.compose-form.state-0 .source-node,.compose-form.state-0 .timeline-progress {\\n    opacity:0\\n}\\n.compose-form.state-0 .post-container {\\n    opacity:0\\n}\\n.compose-form.state-0 .avatar-container {\\n    margin-top:-5px\\n}\\n.compose-form.state-1 {\\n    background:url(/assets/ui/timeline.png) repeat-y 43px 0\\n}\\n.compose-form.state-1 .back-button {\\n    opacity:1\\n}\\n.compose-form.state-1 .next-container {\\n    padding-top:0;\\n    height:0;\\n    min-height:0;\\n    opacity:0\\n}\\n.compose-form.state-1 .post-container {\\n    opacity:1\\n}\\n.topic-header-container.state-1.state-pre-invite.for-twitter {\\n    padding-top:10px\\n}\\nbody .topbar .container {\\n    -webkit-transition:width 0.3s;\\n    -moz-transition:width 0.3s;\\n    -ms-transition:width 0.3s;\\n    -o-transition:width 0.3s;\\n    transition:width 0.3s\\n}\\nbody .compose-state-hideable,body .compose-state-hideable-mobile {\\n    opacity:1;\\n    -webkit-transition:opacity 0.3s;\\n    -moz-transition:opacity 0.3s;\\n    -ms-transition:opacity 0.3s;\\n    -o-transition:opacity 0.3s;\\n    transition:opacity 0.3s\\n}\\n@media (min-width:600px) {\\n    body.compose-state .quick-compose-container {\\n    border-bottom:0;\\n    padding-right:100px\\n}\\nbody.compose-state .topbar .container {\\n    width:620px\\n}\\nbody.compose-state .topbar .container .logotype-container {\\n    margin-left:20px\\n}\\n}body.compose-state .compose-state-hideable {\\n    opacity:0;\\n    visibility:hidden\\n}\\n.is-mobile body.compose-state .compose-state-hideable-mobile {\\n    opacity:0;\\n    visibility:hidden\\n}\\n\",\n\t\t\t\"settings\":\n\t\t\t{\n\t\t\t\t\"buffer_size\": 72142,\n\t\t\t\t\"line_ending\": \"Windows\",\n\t\t\t\t\"name\": \".avenir,.small-caps-avenir,.post-form-host-ctas bu\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"file\": \"/E/code/playjs/mcss/test/specs/test-parser.js\",\n\t\t\t\"settings\":\n\t\t\t{\n\t\t\t\t\"buffer_size\": 180,\n\t\t\t\t\"line_ending\": \"Windows\"\n\t\t\t}\n\t\t}\n\t],\n\t\"build_system\": \"\",\n\t\"command_palette\":\n\t{\n\t\t\"height\": 336.0,\n\t\t\"selected_items\":\n\t\t[\n\t\t\t[\n\t\t\t\t\"new\",\n\t\t\t\t\"Tasks: New document\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"ins\",\n\t\t\t\t\"Package Control: Install Package\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"insl\",\n\t\t\t\t\"Package Control: Install Package\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"remo\",\n\t\t\t\t\"Package Control: Remove Package\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"insta\",\n\t\t\t\t\"Package Control: Install Package\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"gist\",\n\t\t\t\t\"Gist: Create Private Gist\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"co\",\n\t\t\t\t\"Set Syntax: CoffeeScript\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"upda\",\n\t\t\t\t\"Package Control: Upgrade Package\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"install\",\n\t\t\t\t\"Package Control: Install Package\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"instal\",\n\t\t\t\t\"Package Control: Install Package\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"ever\",\n\t\t\t\t\"Send to evernote\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"javas\",\n\t\t\t\t\"Set Syntax: JavaScript\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"less\",\n\t\t\t\t\"Set Syntax: LESS\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"coffe\",\n\t\t\t\t\"Set Syntax: CoffeeScript\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"insal\",\n\t\t\t\t\"Package Control: Install Package\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"insall\",\n\t\t\t\t\"Package Control: Install Package\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\":j\",\n\t\t\t\t\"Format: Javascript\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\":noh\",\n\t\t\t\t\"HTML: Encode Special Characters\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"in\",\n\t\t\t\t\"Markdown Preview: current file in browser\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\":w\",\n\t\t\t\t\":w - Save\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\":q\",\n\t\t\t\t\"Set Syntax: SQL\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"mar\",\n\t\t\t\t\"Markdown Preview: current file in browser\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\":e\",\n\t\t\t\t\":$ - EOF\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\":s/n/N\",\n\t\t\t\t\"Snippet: #!/usr/bin/env\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"ma\",\n\t\t\t\t\"Markdown Preview: current file in browser\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"mark\",\n\t\t\t\t\"Set Syntax: Markdown\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\":help\",\n\t\t\t\t\"Set Syntax: Shell Script (Bash)\"\n\t\t\t]\n\t\t],\n\t\t\"width\": 386.0\n\t},\n\t\"console\":\n\t{\n\t\t\"height\": 166.0\n\t},\n\t\"distraction_free\":\n\t{\n\t\t\"menu_visible\": false,\n\t\t\"show_minimap\": false,\n\t\t\"show_open_files\": false,\n\t\t\"show_tabs\": true,\n\t\t\"side_bar_visible\": false,\n\t\t\"status_bar_visible\": false\n\t},\n\t\"file_history\":\n\t[\n\t\t\"/E/code/playjs/mcss/test/specs/test-parser.js\",\n\t\t\"/D/sublime/Data/Packages/Default/Preferences.sublime-settings\",\n\t\t\"/D/sublime/Data/Packages/User/Preferences.sublime-settings\",\n\t\t\"/E/code/playjs/mcss/benchmarks/private/2bindPredicate.js\",\n\t\t\"/E/code/playjs/mcss/dist/ness-0.0.1.js\",\n\t\t\"/E/code/playjs/mcss/index.html\",\n\t\t\"/E/code/nej/qunit/base/qunit.css\",\n\t\t\"/C/Users/user/Desktop/hosts\",\n\t\t\"/C/Users/user/Documents/hosts\",\n\t\t\"/C/Windows/System32/Drivers/etc/hosts\",\n\t\t\"/C/Users/user/Downloads/ichart.1.1.js\",\n\t\t\"/E/code/blog/test/module.contents.js\",\n\t\t\"/E/code/blog/node_modules/sequelize/lib/dao-factory.js\",\n\t\t\"/E/code/blog/libs/core/ThemeManager.js\",\n\t\t\"/E/code/blog/libs/core/Configure.js\",\n\t\t\"/E/code/blog/libs/nep.js\",\n\t\t\"/E/code/blog/libs/core/mail.js\",\n\t\t\"/E/code/blog/libs/core/wrapper/fs.js\",\n\t\t\"/E/code/blog/modules/content/content.js\",\n\t\t\"/E/code/blog/.gitignore\",\n\t\t\"/E/code/blog/modules/content/models/contents.js\",\n\t\t\"/E/code/blog/modules/comment/models/comments.js\",\n\t\t\"/E/code/blog/test/feture/contents.man.js\",\n\t\t\"/E/code/blog/modules/comment/models/commentMeta.js\",\n\t\t\"/E/code/blog/modules/comment/comment.js\",\n\t\t\"/E/code/blog/modules/content/models/contentMeta.js\",\n\t\t\"/E/code/blog/modules/term/term.js\",\n\t\t\"/E/code/blog/package.json\",\n\t\t\"/E/code/blog/libs/core/db.js\",\n\t\t\"/E/code/blog/node_modules/sequelize/lib/dao.js\",\n\t\t\"/E/code/blog/test/fixture/contents.js\",\n\t\t\"/E/code/blog/node_modules/grunt-contrib-nodeunit/tasks/nodeunit.js\",\n\t\t\"/E/code/blog/test/util/grunt-nodeunit-fix.js\",\n\t\t\"/E/code/blog/test/lib.core.cache.js\",\n\t\t\"/E/code/blog/test/lib.core.configure.js\",\n\t\t\"/E/code/blog/test/lib.core.route.js\",\n\t\t\"/E/code/blog/test/lib.nep.js\",\n\t\t\"/E/code/blog/test/libs.core.module.js\",\n\t\t\"/E/code/blog/test/libs.core.view.js\",\n\t\t\"/E/code/blog/test/fixture/contents.man.js\",\n\t\t\"/E/code/blog/modules/mail/mail.js\",\n\t\t\"/E/code/blog/test/feture\",\n\t\t\"/E/code/blog/tmp/a6f59f2886bc786fba51c1879427c72b\",\n\t\t\"/E/code/blog/blog.sublime-project\",\n\t\t\"/E/code/blog/app.js\",\n\t\t\"/E/code/photo/webshare/WebRoot/mobile2012/webapp/src/css/house/house.css\",\n\t\t\"/D/sublime/sublime_text - 副本.exe\",\n\t\t\"/E/code/blog/config.js\",\n\t\t\"/D/sublime/Data/Packages/Terminal/Terminal.sublime-settings\",\n\t\t\"/D/sublime/Data/Packages/Terminal/Default (Windows).sublime-keymap\",\n\t\t\"/E/code/blog2/.gitignore\",\n\t\t\"/E/code/blog2/conf/conf.json\",\n\t\t\"/E/code/blog2/libs/core/db.js\",\n\t\t\"/E/code/blog2/libs/core/middleware.js\",\n\t\t\"/E/code/blog2/libs/core/Section.js\",\n\t\t\"/E/code/blog2/libs/core/ViewHelper.js\",\n\t\t\"/E/code/blog2/themes/default/views/post/body.js\",\n\t\t\"/E/code/blog2/modules/tag/tag.js\",\n\t\t\"/E/code/blog2/libs/core/Router.js\",\n\t\t\"/E/code/blog2/test/lib.core.route.js\",\n\t\t\"/E/code/blog2/test/libs.core.view.js\",\n\t\t\"/E/code/blog2/test/res/theme/post.html\",\n\t\t\"/E/code/blog2/test/lib.core.configure.js\",\n\t\t\"/E/code/blog2/modules/content/content.js\",\n\t\t\"/E/code/blog2/libs/core/cache.js\",\n\t\t\"/E/code/blog2/modules/content/models/content.js\",\n\t\t\"/E/code/blog2/modules/user/controllers/user.js\",\n\t\t\"/E/code/blog2/libs/core/Module.js\",\n\t\t\"/E/code/blog2/modules/content/controllers/contents.js\",\n\t\t\"/E/code/blog2/README.md\",\n\t\t\"/E/code/blog2/modules/user/models/user.js\",\n\t\t\"/E/code/blog2/public/login.html\",\n\t\t\"/E/code/blog2/libs/helper/util.js\",\n\t\t\"/E/source/calipso/config.json\",\n\t\t\"/D/sublime/Data/Packages/Terminal/Main.sublime-menu\",\n\t\t\"/D/sublime/Data/Packages/Terminal/Terminal.py\",\n\t\t\"/E/code/nes/README.md\",\n\t\t\"/E/code/nes/sizzle/speed/selectors.css\",\n\t\t\"/E/code/nes/test/test2.js\",\n\t\t\"/E/code/nes/test/simle.json\",\n\t\t\"/E/code/nes/test/combo.json\",\n\t\t\"/E/code/nes/test/dom.css\",\n\t\t\"/E/code/nes/test/test2.html\",\n\t\t\"/E/code/nes/vendor/jquery.js\",\n\t\t\"/E/code/nes/nes.js\",\n\t\t\"/E/code/nes/sizzle/sizzle.js\",\n\t\t\"/E/code/nes/case/node.js\",\n\t\t\"/E/code/nes/case/selector.txt\",\n\t\t\"/E/code/nes/case/index.html\",\n\t\t\"/E/code/nes/case/public/index.html\",\n\t\t\"/E/code/nes/vendor/log.js\",\n\t\t\"/E/code/nes/sizzle/speed/frameworks/zest.js\",\n\t\t\"/E/code/nes/test/test.js\",\n\t\t\"/E/code/nes/sizzle/speed/speed.js\",\n\t\t\"/E/code/nes/sizzle/test/index.html\",\n\t\t\"/E/code/nes/sizzle/test/unit/selector.js\",\n\t\t\"/E/code/nes/.gitignore\",\n\t\t\"/E/code/nes/test/test.html\",\n\t\t\"/D/Dropbox/Demo/Selector/README.md\",\n\t\t\"/D/Dropbox/Demo/Selector/test/test2.html\",\n\t\t\"/D/Dropbox/Demo/Selector/test/test2.js\",\n\t\t\"/D/Dropbox/Demo/Selector/nes.js\",\n\t\t\"/D/Dropbox/Demo/Selector/sizzle/speed/selectors.css\",\n\t\t\"/D/Dropbox/Demo/Selector/demo/demo.js\",\n\t\t\"/D/Dropbox/Demo/Selector/test/test.js\",\n\t\t\"/D/Dropbox/Demo/Selector/test/extend_pesudo.js\",\n\t\t\"/D/Dropbox/Demo/Selector/test/extend_operator.js\",\n\t\t\"/D/Dropbox/Demo/Selector/test/extend_combo.js\",\n\t\t\"/D/Dropbox/Demo/Selector/test/extend_rule.js\",\n\t\t\"/D/Dropbox/Demo/Selector/.gitignore\",\n\t\t\"/D/Dropbox/Demo/Selector/selector.md\",\n\t\t\"/D/Dropbox/Demo/Selector/sizzle/speed/frameworks/baidu.js\",\n\t\t\"/D/Dropbox/Demo/Selector/sizzle/speed/speed.js\",\n\t\t\"/E/template/html5/package.json\",\n\t\t\"/E/template/html5/dev/assets/index.html\",\n\t\t\"/E/cla/luobo/src/copy.coffee\",\n\t\t\"/E/source/test.js\",\n\t\t\"/E/netease/移动性能研究/src/web/javascript/system.js\",\n\t\t\"/E/netease/移动性能研究/src/web/javascript/module/index.js\",\n\t\t\"/E/netease/移动性能研究/src/web/package.json\",\n\t\t\"/E/netease/移动性能研究/src/web/app.js\",\n\t\t\"/E/netease/移动性能研究/src/web/html/dashboard.html\",\n\t\t\"/E/cli_app/luobo/package.json\",\n\t\t\"/E/cli_app/luobo/Cakefile\",\n\t\t\"/E/cli_app/luobo/src/index.coffee\",\n\t\t\"/E/webApp/dazuoye/1/public/test/index.html\",\n\t\t\"/F/a87470909/build/demo/moo源码分析/mootools-core-1.3.js\",\n\t\t\"/F/source/mootools-core-1.3.js\"\n\t],\n\t\"find\":\n\t{\n\t\t\"height\": 38.0\n\t},\n\t\"find_in_files\":\n\t{\n\t\t\"height\": 0.0,\n\t\t\"where_history\":\n\t\t[\n\t\t\t\"E:\\\\code\\\\blog\\\\node_modules\\\\sequelize\\\\lib\",\n\t\t\t\"E:\\\\code\\\\blog\\\\libs\",\n\t\t\t\"E:\\\\code\\\\blog2\\\\libs\\\\core\",\n\t\t\t\"\"\n\t\t]\n\t},\n\t\"find_state\":\n\t{\n\t\t\"case_sensitive\": false,\n\t\t\"find_history\":\n\t\t[\n\t\t\t\"Inconsolata\",\n\t\t\t\"RuleList\",\n\t\t\t\"Program\",\n\t\t\t\"(\\\\w*)\",\n\t\t\t\"Expression\",\n\t\t\t\"exports.\",\n\t\t\t\"exports\",\n\t\t\t\"exports.\",\n\t\t\t\"exports\",\n\t\t\t\"this.error\",\n\t\t\t\"inspect\",\n\t\t\t\"Node\",\n\t\t\t\"node\",\n\t\t\t\"Node\",\n\t\t\t\"topLevel\",\n\t\t\t\"@key\",\n\t\t\t\"key-frame\",\n\t\t\t\"pulse\",\n\t\t\t\"error\",\n\t\t\t\"NEWLINE\",\n\t\t\t\"stylesheet\",\n\t\t\t\"topLevel\",\n\t\t\t\"skip\",\n\t\t\t\"this\",\n\t\t\t\"green\",\n\t\t\t\"jQuery\",\n\t\t\t\"getTransitionIndex\",\n\t\t\t\"event\",\n\t\t\t\"this\",\n\t\t\t\"console.log\",\n\t\t\t\"expect\",\n\t\t\t\"proEvent\",\n\t\t\t\"[\\\"']_\",\n\t\t\t\"_\",\n\t\t\t\"callback\",\n\t\t\t\"forEach\",\n\t\t\t\"content\",\n\t\t\t\"title\",\n\t\t\t\"TagsCallback\",\n\t\t\t\"callbackForTag\",\n\t\t\t\"callback\",\n\t\t\t\"Content\",\n\t\t\t\"callback\",\n\t\t\t\"psarallel\",\n\t\t\t\"build\",\n\t\t\t\"createContent\",\n\t\t\t\"series\",\n\t\t\t\"get\",\n\t\t\t\"8001\",\n\t\t\t\"this.attributes\",\n\t\t\t\"addOptionalClassMethods\",\n\t\t\t\"classMethods\",\n\t\t\t\"instanceMethods\",\n\t\t\t\"addOptional\",\n\t\t\t\"classMethods\",\n\t\t\t\"method2\",\n\t\t\t\"method1\",\n\t\t\t\"Contents\",\n\t\t\t\"Content\",\n\t\t\t\"Comments\",\n\t\t\t\"Content\",\n\t\t\t\"belongsTo\",\n\t\t\t\"文章\",\n\t\t\t\"authorId\",\n\t\t\t\"文章主人id\",\n\t\t\t\"order\",\n\t\t\t\"url\",\n\t\t\t\"Content\",\n\t\t\t\"themeFo\",\n\t\t\t\"basePath\",\n\t\t\t\"sub\",\n\t\t\t\"cwd\",\n\t\t\t\"server.path\",\n\t\t\t\"3342\",\n\t\t\t\"this.\",\n\t\t\t\"7\",\n\t\t\t\"res6\",\n\t\t\t\"apply\",\n\t\t\t\"console\",\n\t\t\t\"filter\",\n\t\t\t\"console\",\n\t\t\t\"table\",\n\t\t\t\"body\",\n\t\t\t\"posReg\",\n\t\t\t\"createNth\",\n\t\t\t\"create\",\n\t\t\t\"createNth\",\n\t\t\t\"root\",\n\t\t\t\"el\",\n\t\t\t\"root\",\n\t\t\t\":root\",\n\t\t\t\"Sizzle\",\n\t\t\t\"root\",\n\t\t\t\"elem\",\n\t\t\t\"root\",\n\t\t\t\"nthPrev\",\n\t\t\t\"context\",\n\t\t\t\"createMatch\",\n\t\t\t\"script\",\n\t\t\t\"first\",\n\t\t\t\"nthChild\",\n\t\t\t\"elem\",\n\t\t\t\"empty\",\n\t\t\t\"console\",\n\t\t\t\"debug\",\n\t\t\t\"debbugger\",\n\t\t\t\"selector\",\n\t\t\t\"find\",\n\t\t\t\"nthCache\",\n\t\t\t\"nodeList\",\n\t\t\t\"广泛\",\n\t\t\t\"ncp\",\n\t\t\t\"sys\",\n\t\t\t\"_parent\",\n\t\t\t\"_testParent\",\n\t\t\t\"DOMContentLoaded\",\n\t\t\t\"_node\",\n\t\t\t\"node\",\n\t\t\t\"event\",\n\t\t\t\"addEvent\",\n\t\t\t\"done\",\n\t\t\t\"event\",\n\t\t\t\"_fn\",\n\t\t\t\"_get\",\n\t\t\t\"slice\",\n\t\t\t\"i\",\n\t\t\t\"this\",\n\t\t\t\"distinct\"\n\t\t],\n\t\t\"highlight\": true,\n\t\t\"in_selection\": false,\n\t\t\"preserve_case\": false,\n\t\t\"regex\": true,\n\t\t\"replace_history\":\n\t\t[\n\t\t\t\"exports.$1 = $1\",\n\t\t\t\"3242\",\n\t\t\t\"extend\",\n\t\t\t\"m1\",\n\t\t\t\"m2\",\n\t\t\t\"m1\",\n\t\t\t\"\"\n\t\t],\n\t\t\"reverse\": false,\n\t\t\"show_context\": true,\n\t\t\"use_buffer2\": true,\n\t\t\"whole_word\": false,\n\t\t\"wrap\": false\n\t},\n\t\"groups\":\n\t[\n\t\t{\n\t\t\t\"selected\": 1,\n\t\t\t\"sheets\":\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\t\"buffer\": 0,\n\t\t\t\t\t\"file\": \"/E/code/playjs/mcss/lib/tokenizer.js\",\n\t\t\t\t\t\"settings\":\n\t\t\t\t\t{\n\t\t\t\t\t\t\"buffer_size\": 11077,\n\t\t\t\t\t\t\"regions\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"selection\":\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t8904,\n\t\t\t\t\t\t\t\t8904\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"settings\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"syntax\": \"Packages/JavaScript/JavaScript.tmLanguage\",\n\t\t\t\t\t\t\t\"tab_size\": 4,\n\t\t\t\t\t\t\t\"translate_tabs_to_spaces\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"translation.x\": 0.0,\n\t\t\t\t\t\t\"translation.y\": 3058.0,\n\t\t\t\t\t\t\"zoom_level\": 1.0\n\t\t\t\t\t},\n\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"buffer\": 1,\n\t\t\t\t\t\"file\": \"/E/code/playjs/mcss/lib/parser.js\",\n\t\t\t\t\t\"settings\":\n\t\t\t\t\t{\n\t\t\t\t\t\t\"buffer_size\": 9655,\n\t\t\t\t\t\t\"regions\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"selection\":\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t6732,\n\t\t\t\t\t\t\t\t6732\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"settings\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"syntax\": \"Packages/JavaScript/JavaScript.tmLanguage\",\n\t\t\t\t\t\t\t\"tab_size\": 4,\n\t\t\t\t\t\t\t\"translate_tabs_to_spaces\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"translation.x\": 0.0,\n\t\t\t\t\t\t\"translation.y\": 5165.0,\n\t\t\t\t\t\t\"zoom_level\": 1.0\n\t\t\t\t\t},\n\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"buffer\": 2,\n\t\t\t\t\t\"file\": \"/D/sublime/Data/Packages/User/Preferences.sublime-settings\",\n\t\t\t\t\t\"settings\":\n\t\t\t\t\t{\n\t\t\t\t\t\t\"buffer_size\": 416,\n\t\t\t\t\t\t\"regions\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"selection\":\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t102,\n\t\t\t\t\t\t\t\t102\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"settings\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"syntax\": \"Packages/AAAPackageDev/Support/Sublime Settings.tmLanguage\",\n\t\t\t\t\t\t\t\"translate_tabs_to_spaces\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"translation.x\": 0.0,\n\t\t\t\t\t\t\"translation.y\": 0.0,\n\t\t\t\t\t\t\"zoom_level\": 1.0\n\t\t\t\t\t},\n\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"buffer\": 3,\n\t\t\t\t\t\"file\": \"/E/code/playjs/mcss/test/data/parse.mcss\",\n\t\t\t\t\t\"settings\":\n\t\t\t\t\t{\n\t\t\t\t\t\t\"buffer_size\": 43,\n\t\t\t\t\t\t\"regions\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"selection\":\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t21,\n\t\t\t\t\t\t\t\t21\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"settings\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"syntax\": \"Packages/Text/Plain text.tmLanguage\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"translation.x\": 0.0,\n\t\t\t\t\t\t\"translation.y\": 0.0,\n\t\t\t\t\t\t\"zoom_level\": 1.0\n\t\t\t\t\t},\n\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"buffer\": 4,\n\t\t\t\t\t\"file\": \"/E/code/playjs/mcss/test/data/simple.mcss\",\n\t\t\t\t\t\"settings\":\n\t\t\t\t\t{\n\t\t\t\t\t\t\"buffer_size\": 8084,\n\t\t\t\t\t\t\"regions\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"selection\":\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t8029,\n\t\t\t\t\t\t\t\t8029\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"settings\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"syntax\": \"Packages/Text/Plain text.tmLanguage\",\n\t\t\t\t\t\t\t\"tab_size\": 4,\n\t\t\t\t\t\t\t\"translate_tabs_to_spaces\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"translation.x\": 0.0,\n\t\t\t\t\t\t\"translation.y\": 11462.0,\n\t\t\t\t\t\t\"zoom_level\": 1.0\n\t\t\t\t\t},\n\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"buffer\": 5,\n\t\t\t\t\t\"file\": \"/E/code/playjs/mcss/test/specs/test-tokenizer.js\",\n\t\t\t\t\t\"settings\":\n\t\t\t\t\t{\n\t\t\t\t\t\t\"buffer_size\": 3057,\n\t\t\t\t\t\t\"regions\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"selection\":\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t2924,\n\t\t\t\t\t\t\t\t2924\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"settings\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"syntax\": \"Packages/JavaScript/JavaScript.tmLanguage\",\n\t\t\t\t\t\t\t\"tab_size\": 4,\n\t\t\t\t\t\t\t\"translate_tabs_to_spaces\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"translation.x\": 0.0,\n\t\t\t\t\t\t\"translation.y\": 1770.0,\n\t\t\t\t\t\t\"zoom_level\": 1.0\n\t\t\t\t\t},\n\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"buffer\": 6,\n\t\t\t\t\t\"file\": \"/E/code/playjs/mcss/test/browser/index.html\",\n\t\t\t\t\t\"settings\":\n\t\t\t\t\t{\n\t\t\t\t\t\t\"buffer_size\": 606,\n\t\t\t\t\t\t\"regions\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"selection\":\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t529,\n\t\t\t\t\t\t\t\t529\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"settings\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"is_xml\": false,\n\t\t\t\t\t\t\t\"syntax\": \"Packages/HTML/HTML.tmLanguage\",\n\t\t\t\t\t\t\t\"tab_size\": 2,\n\t\t\t\t\t\t\t\"translate_tabs_to_spaces\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"translation.x\": 0.0,\n\t\t\t\t\t\t\"translation.y\": 0.0,\n\t\t\t\t\t\t\"zoom_level\": 1.0\n\t\t\t\t\t},\n\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"buffer\": 7,\n\t\t\t\t\t\"file\": \"/E/code/playjs/mcss/lib/browser.js\",\n\t\t\t\t\t\"settings\":\n\t\t\t\t\t{\n\t\t\t\t\t\t\"buffer_size\": 191,\n\t\t\t\t\t\t\"regions\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"selection\":\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t186,\n\t\t\t\t\t\t\t\t186\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"settings\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"syntax\": \"Packages/JavaScript/JavaScript.tmLanguage\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"translation.x\": 0.0,\n\t\t\t\t\t\t\"translation.y\": 0.0,\n\t\t\t\t\t\t\"zoom_level\": 1.0\n\t\t\t\t\t},\n\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"buffer\": 8,\n\t\t\t\t\t\"file\": \"/E/code/playjs/mcss/lib/helper/util.js\",\n\t\t\t\t\t\"settings\":\n\t\t\t\t\t{\n\t\t\t\t\t\t\"buffer_size\": 1741,\n\t\t\t\t\t\t\"regions\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"selection\":\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t1715,\n\t\t\t\t\t\t\t\t1715\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"settings\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"syntax\": \"Packages/JavaScript/JavaScript.tmLanguage\",\n\t\t\t\t\t\t\t\"tab_size\": 2,\n\t\t\t\t\t\t\t\"translate_tabs_to_spaces\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"translation.x\": 0.0,\n\t\t\t\t\t\t\"translation.y\": 660.0,\n\t\t\t\t\t\t\"zoom_level\": 1.0\n\t\t\t\t\t},\n\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"buffer\": 9,\n\t\t\t\t\t\"file\": \"/E/code/playjs/mcss/dist/mcss-0.0.1.js\",\n\t\t\t\t\t\"settings\":\n\t\t\t\t\t{\n\t\t\t\t\t\t\"buffer_size\": 35839,\n\t\t\t\t\t\t\"regions\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"selection\":\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t0\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"settings\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"syntax\": \"Packages/JavaScript/JavaScript.tmLanguage\",\n\t\t\t\t\t\t\t\"tab_size\": 4,\n\t\t\t\t\t\t\t\"translate_tabs_to_spaces\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"translation.x\": 0.0,\n\t\t\t\t\t\t\"translation.y\": 0.0,\n\t\t\t\t\t\t\"zoom_level\": 1.0\n\t\t\t\t\t},\n\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"buffer\": 10,\n\t\t\t\t\t\"file\": \"/E/code/playjs/mcss/benchmarks/private/predict.js\",\n\t\t\t\t\t\"settings\":\n\t\t\t\t\t{\n\t\t\t\t\t\t\"buffer_size\": 0,\n\t\t\t\t\t\t\"regions\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"selection\":\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t0\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"settings\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"syntax\": \"Packages/JavaScript/JavaScript.tmLanguage\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"translation.x\": 0.0,\n\t\t\t\t\t\t\"translation.y\": 0.0,\n\t\t\t\t\t\t\"zoom_level\": 1.0\n\t\t\t\t\t},\n\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"buffer\": 11,\n\t\t\t\t\t\"file\": \"/E/code/playjs/mcss/lib/node/index.js\",\n\t\t\t\t\t\"settings\":\n\t\t\t\t\t{\n\t\t\t\t\t\t\"buffer_size\": 622,\n\t\t\t\t\t\t\"regions\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"selection\":\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t410,\n\t\t\t\t\t\t\t\t410\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"settings\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"syntax\": \"Packages/JavaScript/JavaScript.tmLanguage\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"translation.x\": 0.0,\n\t\t\t\t\t\t\"translation.y\": 0.0,\n\t\t\t\t\t\t\"zoom_level\": 1.0\n\t\t\t\t\t},\n\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"buffer\": 12,\n\t\t\t\t\t\"settings\":\n\t\t\t\t\t{\n\t\t\t\t\t\t\"buffer_size\": 72142,\n\t\t\t\t\t\t\"regions\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"selection\":\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t67874,\n\t\t\t\t\t\t\t\t67874\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"settings\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"auto_name\": \".avenir,.small-caps-avenir,.post-form-host-ctas bu\",\n\t\t\t\t\t\t\t\"default_dir\": \"E:\\\\code\\\\playjs\\\\mcss\\\\docs\\\\public\",\n\t\t\t\t\t\t\t\"is_xml\": false,\n\t\t\t\t\t\t\t\"syntax\": \"Packages/Text/Plain text.tmLanguage\",\n\t\t\t\t\t\t\t\"tab_size\": 4,\n\t\t\t\t\t\t\t\"translate_tabs_to_spaces\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"translation.x\": 0.0,\n\t\t\t\t\t\t\"translation.y\": 47802.0,\n\t\t\t\t\t\t\"zoom_level\": 1.0\n\t\t\t\t\t},\n\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"selected\": 0,\n\t\t\t\"sheets\":\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\t\"buffer\": 13,\n\t\t\t\t\t\"file\": \"/E/code/playjs/mcss/test/specs/test-parser.js\",\n\t\t\t\t\t\"settings\":\n\t\t\t\t\t{\n\t\t\t\t\t\t\"buffer_size\": 180,\n\t\t\t\t\t\t\"regions\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"selection\":\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t137,\n\t\t\t\t\t\t\t\t137\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"settings\":\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"syntax\": \"Packages/JavaScript/JavaScript.tmLanguage\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"translation.x\": 0.0,\n\t\t\t\t\t\t\"translation.y\": 0.0,\n\t\t\t\t\t\t\"zoom_level\": 1.0\n\t\t\t\t\t},\n\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t],\n\t\"incremental_find\":\n\t{\n\t\t\"height\": 36.0\n\t},\n\t\"input\":\n\t{\n\t\t\"height\": 38.0\n\t},\n\t\"layout\":\n\t{\n\t\t\"cells\":\n\t\t[\n\t\t\t[\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\t1,\n\t\t\t\t1\n\t\t\t],\n\t\t\t[\n\t\t\t\t1,\n\t\t\t\t0,\n\t\t\t\t2,\n\t\t\t\t1\n\t\t\t]\n\t\t],\n\t\t\"cols\":\n\t\t[\n\t\t\t0.0,\n\t\t\t0.565659500291,\n\t\t\t1.0\n\t\t],\n\t\t\"rows\":\n\t\t[\n\t\t\t0.0,\n\t\t\t1.0\n\t\t]\n\t},\n\t\"menu_visible\": false,\n\t\"output.exec\":\n\t{\n\t\t\"height\": 162.0\n\t},\n\t\"replace\":\n\t{\n\t\t\"height\": 66.0\n\t},\n\t\"save_all_on_build\": true,\n\t\"select_file\":\n\t{\n\t\t\"height\": 0.0,\n\t\t\"selected_items\":\n\t\t[\n\t\t\t[\n\t\t\t\t\"test-p\",\n\t\t\t\t\"mcss/test/specs/test-parser.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"nes\",\n\t\t\t\t\"mcss/dist/ness-0.0.1.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"modelcontents\",\n\t\t\t\t\"modules/content/models/contents.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"modelcontent\",\n\t\t\t\t\"modules/content/models/contents.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"coremail\",\n\t\t\t\t\"libs/core/mail.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"config\",\n\t\t\t\t\"libs/core/Configure.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"config.js\",\n\t\t\t\t\"blog/config.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"body.js\",\n\t\t\t\t\"blog2/themes/default/views/post/body.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"viewh\",\n\t\t\t\t\"blog2/libs/core/ViewHelper.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"section.js\",\n\t\t\t\t\"blog2/libs/core/Section.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"extend_ru\",\n\t\t\t\t\"Selector/test/extend_rule.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"extendco.js\",\n\t\t\t\t\"Selector/test/extend_combo.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"extend_op.js\",\n\t\t\t\t\"Selector/test/extend_operator.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"extend_pesudo\",\n\t\t\t\t\"Selector/test/extend_pesudo.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"test.js\",\n\t\t\t\t\"Selector/test/test.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"dev\",\n\t\t\t\t\"dev/assets/index.html\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"pa\",\n\t\t\t\t\"package.json\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"d\",\n\t\t\t\t\"dev/assets/index.html\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"index.co\",\n\t\t\t\t\"src/index.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"cop\",\n\t\t\t\t\"src/copy.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"copc\",\n\t\t\t\t\"src/copy.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"testinde\",\n\t\t\t\t\"test/assets/test/index.html\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"utit\",\n\t\t\t\t\"test/utils_test.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"uti\",\n\t\t\t\t\"app/util.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"testindex\",\n\t\t\t\t\"test/assets/test/index.html\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"style\",\n\t\t\t\t\"public/css/style.css\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"ven\",\n\t\t\t\t\"app/views/styles/vendor.less\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"sytlele\",\n\t\t\t\t\"app/views/styles/style.less\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"ut\",\n\t\t\t\t\"app/util.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"util\",\n\t\t\t\t\"app/util.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"con\",\n\t\t\t\t\"config.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"hep\",\n\t\t\t\t\"node_modules/auto-reload-brunch/node_modules/coffee-script/lib/coffee-script/helpers.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"test/in\",\n\t\t\t\t\"public/test/index.html\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"conf\",\n\t\t\t\t\"config.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"styll\",\n\t\t\t\t\"app/views/styles/style.less\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"app\",\n\t\t\t\t\"app/app.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"styl\",\n\t\t\t\t\"public/css/style.css\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"stylel\",\n\t\t\t\t\"app/views/styles/style.less\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"st\",\n\t\t\t\t\"public/css/style.css\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"sty\",\n\t\t\t\t\"public/css/style.css\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"ve\",\n\t\t\t\t\"app/views/styles/vendor.less\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"sless\",\n\t\t\t\t\"app/views/styles/style.less\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"co\",\n\t\t\t\t\"config.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"bin/b\",\n\t\t\t\t\"bin/brunch\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"luobo\",\n\t\t\t\t\"/F/JsCandy/luobo/bin/luobo\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"cof\",\n\t\t\t\t\"tasks/coffee.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"coffee.js\",\n\t\t\t\t\"node_modules/grunt-contrib/tasks/coffee.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"g\",\n\t\t\t\t\"grunt.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"grun\",\n\t\t\t\t\"grunt.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"applica\",\n\t\t\t\t\"app/application.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"confi\",\n\t\t\t\t\"config.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"mai\",\n\t\t\t\t\"public/js/main.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"he\",\n\t\t\t\t\"public/js/helper.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"appsty\",\n\t\t\t\t\"app/views/styles/style.css\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"appinde\",\n\t\t\t\t\"app/assets/index.html\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"inde\",\n\t\t\t\t\"app/assets/index.html\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"views\",\n\t\t\t\t\"app/views/styles/style.css\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"pac\",\n\t\t\t\t\"package.json\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"main\",\n\t\t\t\t\"public/js/main.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"grunt\",\n\t\t\t\t\"grunt.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"c\",\n\t\t\t\t\"config.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"modedemo\",\n\t\t\t\t\"app/models/demo.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"demoh\",\n\t\t\t\t\"app/views/templates/demo.hbs\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"home\",\n\t\t\t\t\"app/views/templates/home.hbs\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"demo\",\n\t\t\t\t\"app/models/demo.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"appli\",\n\t\t\t\t\"app/application.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"ini\",\n\t\t\t\t\"app/initialize.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"ap\",\n\t\t\t\t\"app/application.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"tes\",\n\t\t\t\t\"app/test.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"te\",\n\t\t\t\t\"node_modules/jsdom/node_modules/request/tests/test-errors.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"app.j\",\n\t\t\t\t\"public/javascripts/app.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"in\",\n\t\t\t\t\"app/initialize.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"modelsde\",\n\t\t\t\t\"app/models/demo.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"spe\",\n\t\t\t\t\"test/spec.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"s\",\n\t\t\t\t\"test/spec.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"publictests\",\n\t\t\t\t\"public/test/tests.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"sp\",\n\t\t\t\t\"test/spec.coffee\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"user\",\n\t\t\t\t\"test/models/user_test.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"a\",\n\t\t\t\t\"app.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"math\",\n\t\t\t\t\"js/math.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"l07\",\n\t\t\t\t\"js/lesson/l07.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"ma\",\n\t\t\t\t\"Makefile\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"test\",\n\t\t\t\t\"js/test.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"gh\",\n\t\t\t\t\"js/gh.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"gru\",\n\t\t\t\t\"grunt.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"pre\",\n\t\t\t\t\"/D/sublime/Data/Packages/User/Preferences.sublime-settings\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"web/main\",\n\t\t\t\t\"webgl/js/main.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"vec3\",\n\t\t\t\t\"webgl-matrix-benchmarks/libs/closure/goog/vec/vec3.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"clovec\",\n\t\t\t\t\"webgl-matrix-benchmarks/libs/closure/goog/vec/vec4.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"vec\",\n\t\t\t\t\"webgl-matrix-benchmarks/libs/closure/goog/vec/vec.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"closure.js\",\n\t\t\t\t\"webgl-matrix-benchmarks/libs/closure/goog/vec/mat4.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"index\",\n\t\t\t\t\"index.html\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"vc\",\n\t\t\t\t\"math/Vec2.js\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"publicin\",\n\t\t\t\t\"public/index.html\"\n\t\t\t]\n\t\t],\n\t\t\"width\": 0.0\n\t},\n\t\"select_project\":\n\t{\n\t\t\"height\": 500.0,\n\t\t\"selected_items\":\n\t\t[\n\t\t\t[\n\t\t\t\t\"pla\",\n\t\t\t\t\"/E/code/nej/qunit/html/util/chain/playjs.sublime-project\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"doc\",\n\t\t\t\t\"/E/docs/docs.sublime-project\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"ne\",\n\t\t\t\t\"/E/code/reports/yemianqiefen/nej.sublime-project\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"blo\",\n\t\t\t\t\"/E/code/blog/blog.sublime-project\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"photo\",\n\t\t\t\t\"/E/code/photo/photo.sublime-project\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"ph\",\n\t\t\t\t\"/E/code/photo/photo.sublime-project\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"\",\n\t\t\t\t\"/E/netease/移动性能研究/src/web/nej.sublime-project\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"z\",\n\t\t\t\t\"/E/webApp/dazuoye/1/zuoye1.sublime-project\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"zuo\",\n\t\t\t\t\"/F/webApp/zuoye/zuoye.sublime-project\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"brunch\",\n\t\t\t\t\"/F/source/brunch/brunch-source.sublime-project\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"we\",\n\t\t\t\t\"/F/JsCandy/webgl/webgl.sublime-project\"\n\t\t\t],\n\t\t\t[\n\t\t\t\t\"b\",\n\t\t\t\t\"/F/blogs/leeluolee.github.com/source/blogs.sublime-project\"\n\t\t\t]\n\t\t],\n\t\t\"width\": 380.0\n\t},\n\t\"show_minimap\": false,\n\t\"show_open_files\": false,\n\t\"show_tabs\": true,\n\t\"side_bar_visible\": true,\n\t\"side_bar_width\": 199.0,\n\t\"status_bar_visible\": true\n}\n"
  },
  {
    "path": "src/util/chart/chart.js",
    "content": "/*\n * 图表实现文件\n * @author cheng-lin(cheng-lin@corp.netease.com)\n * @version 1.0\n */\n/** @module util/chart/chart */\nNEJ.define([\n    'base/global',\n    'base/config',\n    'base/element',\n    'util/flash/flash',\n    'base/chain'\n],function(NEJ,_c,_e,_t0,_x,_p,_o,_f,_r){\n    /**\n     * 绘制图表对象\n     *\n     * 页面结构举例\n     * ```html\n     * <div id='box'></div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/chart/chart'\n     * ],function(_t0,_p,_o,_f,_r){\n     *     _t0._$drawChart('box',{data:{}})\n     * });\n     * ```\n     *\n     * @method   module:util/chart/chart._$drawChart\n     * @param    {String|Node} box     - 图表父节点\n     * @param    {Object}      options - 可配置参数\n     * @property {Object}      data    - 生成图表需要的数据\n     * @return   {Void}\n     */\n    /**\n     * @method CHAINABLE._$request\n     * @see module:util/chart/chart._$request\n     */\n    _p._$drawChart = function(_box,_options){\n        _box = _e._$get(_box)||_o;\n        _t0._$flash({\n            parent:_box,\n            width:_options.width||'100%',\n            height:_options.height||'100%',\n            src:_c._$get('chart.swf'),\n            params:{wmode:'transparent'},\n            onready:function(_flash){\n                _flash.initChart(_options.data);\n            }._$bind(this)\n        });\n    };\n    // for chainable method\n    _x._$merge(_p);\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.e'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/clipboard/clipboard.js",
    "content": "/*\n * ------------------------------------------\n * 剪切板操作接口支持实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/clipboard/clipboard */\nNEJ.define([\n    'base/global',\n    'base/config',\n    'base/util',\n    'base/element',\n    'base/chain',\n    'util/flash/flash'\n],function(NEJ,_c,_u,_e,_x,_t0,_p,_o,_f,_r){\n    /*\n     * 覆盖剪切操作功能按钮\n     * @param  {Node}   按钮\n     * @param  {String} 参数\n     * @return {Void}\n     */\n    var _doCoverClipboard = function(_element,_vars,_options){\n        // build holder\n        var _box = _e._$wrapInline(_element),\n            _height = _element.offsetHeight;\n        _e._$style(_box,{\n            left:'-1px',\n            height:_height+1+'px',\n            width:_element.offsetWidth+1+'px',\n            top:Math.floor((_box.parentNode.offsetHeight-_height)/2)+'px'\n        });\n        // cover flash\n        _t0._$flash(_u._$merge({\n            parent:_box,\n            target:_element,\n            width:'100%',height:'100%',\n            src:_c._$get('clipboard.swf'),\n            params:{\n                flashvars: _vars,\n                wmode: 'transparent',\n                allowscriptaccess: 'always'\n            }\n        },_options));\n        return _box;\n    };\n    /**\n     * 绑定复制操作，服务器放置剪切板操作Flash nej_clipboard.swf，\n     * 如果flash文件不在/res/下可以通过以下方式配置\n     *\n     * 脚本举例\n     * ```javascript\n     *   // 在引入define之前配置NEJ\n     *   window.NEJ_CONF ={\n     *       clipboard:'/other/path/nej_clipboard.swf'\n     *   };\n     * ```\n     *\n     * 页面结构\n     * ```html\n     *   <!-- 复制按钮 -->\n     *   <input id=\"copyBtn\" type=\"button\" value=\"复制\"/>\n     * ```\n     *\n     * 脚本绑定复制功能\n     * ```javascript\n     * NEJ.define([\n     *     'util/clipboard/clipboard'\n     * ],function(_e){\n     *     // 或者通过参数在绑定时输入要复制的内容\n     *     _e._$copy('copyBtn','text to clipboard');\n     *     // 如果要复制的内容动态生成\n     *     _e._$copy('copyBtn',function(){\n     *         // 此函数必须同步返回结果\n     *         return 'text to clipboard'\n     *     });\n     * });\n     * ```\n     *\n     * @method module:util/clipboard/clipboard._$copy\n     * @param  {String|Node}     arg0 - 操作节点\n     * @param  {String|Function} arg1 - 要复制的内容，或者动态生成要复制的内容\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$copy\n     * @see module:util/clipboard/clipboard._$copy\n     */\n    _p._$copy = function(_element,_content){\n        _element = _e._$get(_element);\n        if (!_element) return;\n        // bind flash\n        return _doCoverClipboard(_element,'op=0',{\n            onbeforecopy:function(){\n                return _u._$isFunction(_content)?_content():(_content||'');\n            }\n        });\n    };\n    /**\n     * 清空剪切板，服务器放置剪切板操作Flash nej_clipboard.swf，\n     * 如果flash文件不在/res/下可以通过以下方式配置\n     *\n     * 脚本举例\n     * ```javascript\n     *   // 在引入define之前配置NEJ\n     *   window.NEJ_CONF ={\n     *       clipboard:'/other/path/nej_clipboard.swf'\n     *   };\n     * ```\n     *\n     * 页面结构\n     * ```html\n     *   <!-- 粘贴按钮 -->\n     *   <input id=\"clearBtn\" type=\"button\" value=\"清空\"/>\n     * ```\n     *\n     * 脚本绑定清空功能\n     * ```javascript\n     * NEJ.define([\n     *     'util/clipboard/clipboard'\n     * ],function(_e){\n     *     // 绑定清空按钮功能\n     *     _e._$clear('clearBtn');\n     * });\n     * ```\n     *\n     * @method module:util/clipboard/clipboard._$clear\n     * @param  {String|Node} arg0 - 操作节点\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$clear\n     * @see module:util/clipboard/clipboard._$clear\n     */\n    _p._$clear =  function(_element){\n        _element = _e._$get(_element);\n        if (!_element) return;\n        return _doCoverClipboard(_element,'op=2');\n    };\n    // for chainable method\n    _x._$merge(_p);\n\n    if (CMPT){\n        var _x = NEJ.P('nej.e');\n        _x._$bindCopyAction = _p._$copy;\n        _x._$bindClearAction = _p._$clear;\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/clipboard/demo/clipboard.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test clipboard</title>\n    <meta charset=\"utf-8\"/>\n  </head>\n  <body title=\"123456789\">\n\n    <input type=\"button\" value=\"复制\" id=\"xx\"/>\n\n    <script src=\"../../../define.js\"></script>\n    <script>\n      define([\n          '../clipboard.js'\n      ],function(_e){\n          _e._$copy('xx',function(node){\n              console.log('xxxx');\n              return node.title;\n          }._$bind(null,document.body));\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/clipboard/test/clipboard.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>clipboard测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit xdr test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./clipboard.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/clipboard/test/clipboard.test.js",
    "content": "NEJ.define(['util/clipboard/clipboard'],function(){\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v');\n    test('clipboard',function(){\n        expect(0);\n        _e._$bindCopyAction('copyBtn','text to clipboard');\n    });\n});"
  },
  {
    "path": "src/util/clipper/clipper.js",
    "content": "/*\n * ------------------------------------------\n * 图片裁剪器封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/clipper/clipper */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/constant',\n    'base/element',\n    'base/util',\n    'util/event',\n    'ui/resizer/resizer'\n],function(NEJ,_k,_g,_e,_u,_t,_i,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 图片裁剪器封装对象\n     *\n     * 样式举例\n     * ```css\n     * .test{padding:20px;overflow:hidden;}\n     * .box{border:1px solid #aaa;}\n     * .mbox{position:relative;float:left;width:500px;height:500px;margin-right:-500px;}\n     * .prev{margin-left:500px;padding-left:20px;}\n     * .pbox{position:relative;margin-bottom:10px;overflow:hidden;}\n     * .pbox-0{width:80px;height:80px;}\n     * .pbox-1{width:120px;height:120px;}\n     * .pbox-2{width:200px;height:200px;}\n     * ```\n     * \n     * 结构举例\n     * ```html\n     * <div class=\"test\">\n     *   <!-- 裁剪区 -->\n     *   <div class=\"box mbox\" id=\"clip-main\"></div>\n     *   <!-- 预览区 -->\n     *   <div class=\"prev\">\n     *     <div class=\"box pbox pbox-0\" id=\"clip-preview-0\"></div>\n     *     <div class=\"box pbox pbox-1\" id=\"clip-preview-1\"></div>\n     *     <div class=\"box pbox pbox-2\" id=\"clip-preview-2\"></div>\n     *   </div>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/clipper/clipper'\n     * ],function(_t){\n     *     var _clipper = _t._$$Clipper._$allocate({\n     *         url:'./4.jpg',\n     *         mbox:'clip-main',\n     *         lock:!0,\n     *         pbox:[\n     *             'clip-preview-0',\n     *             'clip-preview-1',\n     *             'clip-preview-2'\n     *         ],\n     *         size:{\n     *             ratio:1,\n     *             width:80\n     *         }\n     *     });\n     * });\n     * ```\n     * \n     * @class    module:util/clipper/clipper._$$Clipper\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object}            config - 可选配置参数\n     * @property {String|Node}       mbox   - 裁剪容器节点\n     * @property {String|Node|Array} pbox   - 预览容器节点 \n     * @property {String}            url    - 图片地址\n     * @property {Boolean}           lock   - 是否锁定比例\n     * @property {Object}            size   - 裁剪缩放器初始大小\n     */\n    /** \n     * 图片载入之前事件\n     * \n     * @event    module:util/clipper/clipper._$$Clipper#onbeforeimageload\n     * @param    {Object}  event  - 事件信息\n     * @property {Node}    parent - 容器节点\n     */\n    /** \n     * 图片载入之后事件\n     * \n     * @event    module:util/clipper/clipper._$$Clipper#onafterimageload\n     * @param    {Object}  event  - 事件信息\n     * @property {Node}    parent - 容器节点\n     * @property {Boolean} loaded - 图片是否成功载入\n     */\n    /** \n     * 图片显示之后事件\n     * \n     * @event    module:util/clipper/clipper._$$Clipper#onafterimageshow\n     * @param    {Object}  event  - 事件信息\n     * @property {Node}    parent - 容器节点\n     * @property {Float}   ratio  - 图片缩放比例，显示大小/原始大小\n     * @property {Object}  value  - 大小调整对象或者大小调整对象配置信息\n     */\n    /** \n     * 裁剪位置变化事件\n     * \n     * @event    module:util/clipper/clipper._$$Clipper#onchange\n     * @param    {Object} event  - 裁剪信息\n     * @property {Float}  ratio  - 图片缩放比例\n     * @property {NUmber} top    - 裁剪距顶部位置\n     * @property {NUmber} left   - 裁剪距左侧位置\n     * @property {NUmber} width  - 裁剪宽度\n     * @property {NUmber} height - 裁剪高度\n     */\n    _p._$$Clipper = _k._$klass();\n    _pro = _p._$$Clipper._$extend(_t._$$EventTarget);\n    /**\n     * 控件初始化\n     * \n     * @protected\n     * @method module:util/clipper/clipper._$$Clipper#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__image = new Image();\n        this.__ropt = {\n            onmove:this.__onClipping._$bind(this),\n            onresize:this.__onClipping._$bind(this)\n        };\n        this.__super();\n    };\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/clipper/clipper._$$Clipper#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        // init event\n        this.__doInitDomEvent([[\n            this.__image,'load',\n            this.__onImageLoad._$bind(this,!0)\n        ],[\n            this.__image,'error',\n            this.__onImageLoad._$bind(this,!1)\n        ]]);\n        // init node\n        this.__pbox = {};\n        this.__mbox = _e._$get(_options.mbox);\n        this.__sopt = _u._$fetch({\n            lock:!1,\n            size:null\n        },_options);\n        var _preview = _options.pbox;\n        if (!_u._$isArray(_preview)){\n            this._$addPreview(_preview);\n        }else{\n            _u._$forEach(\n                _preview,this._$addPreview,this\n            );\n        }\n        this._$setURL(_options.url);\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/clipper/clipper._$$Clipper#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        this.__doClearResizer();\n        this.__doClearPreview();\n        this.__image.src = _g._$BLANK_IMAGE;\n    };\n    /**\n     * 清除缩放器\n     * \n     * @protected\n     * @method module:util/clipper/clipper._$$Clipper#__doClearResizer\n     * @return {Void}\n     */\n    _pro.__doClearResizer = function(){\n        _e._$remove(this.__cbox);\n        delete this.__cbox;\n        if (!!this.__resizer){\n            this.__resizer._$recycle();\n            delete this.__resizer;\n        }\n    };\n    /**\n     * 清除预览图片\n     * \n     * @protected\n     * @method module:util/clipper/clipper._$$Clipper#__doClearPreview\n     * @return {Void}\n     */\n    _pro.__doClearPreview = function(_keeped){\n        _u._$forIn(\n            this.__pbox,function(_conf){\n                var _img = _e._$get(_conf.img);\n                if (!_img) return;\n                if (!_keeped){\n                    _e._$remove(_img);\n                }else{\n                    _img.src = _g._$BLANK_IMAGE;\n                }\n            }\n        );\n    };\n    /**\n     * 计算图片位置\n     * \n     * @protected\n     * @method module:util/clipper/clipper._$$Clipper#__doCalImagePosition\n     * @param  {Object} arg0 - 图片尺寸，{width:10,height:20}\n     * @param  {Object} arg1 - 容器尺寸，{width:200,height:300}\n     * @return {Object}        图片位置，{left:0,top:0,width:10,height:20}\n     */\n    _pro.__doCalImagePosition = function(_simg,_sbox){\n        var _irat = _simg.width/_simg.height,\n            _brat = _sbox.width/_sbox.height,\n            _result = {};\n        if (_brat<_irat&&_sbox.width<_simg.width){\n            // width overflow\n            _result.width = _sbox.width;\n            _result.height = Math.floor(_result.width/_irat);\n        }else if(_brat>_irat&&_sbox.height<_simg.height){\n            // height overflow\n            _result.height = _sbox.height;\n            _result.width = Math.floor(_result.height*_irat);\n        }else{\n            // no overflow\n            _result.width = _simg.width;\n            _result.height = _simg.height;\n        }\n        _result.left = Math.floor((_sbox.width-_result.width)/2);\n        _result.top = Math.floor((_sbox.height-_result.height)/2);\n        _result.ratio = _result.width/_simg.width;\n        return _result;\n    };\n    /**\n     * 计算裁剪预览位置\n     * \n     * @protected\n     * @method module:util/clipper/clipper._$$Clipper#__doCalClipPosition\n     * @return {Void}\n     */\n    _pro.__doCalClipPosition = function(_clip,_prev){\n        var _result = {},\n            _ratio = _clip.width/_prev.width,\n            _delta = this.__ratio/_ratio;\n        _result.top = Math.floor(_clip.top/_ratio);\n        _result.left = Math.floor(_clip.left/_ratio);\n        _result.width = Math.floor(this.__image.width*_delta);\n        _result.height = Math.floor(this.__image.height*_delta);\n        return _result;\n    };\n    /**\n     * 图片载入完成触发事件\n     * \n     * @protected\n     * @method module:util/clipper/clipper._$$Clipper#__onImageLoad\n     * @param  {Boolean} arg0 - 图片是否成功载入\n     * @return {Void}\n     */\n    _pro.__onImageLoad = (function(){\n        var _imgsize = {\n            position:'absolute',\n            top:0,left:0,\n            width:'100%',\n            height:'100%'\n        };\n        var _doAppendUnit = function(_map){\n            _u._$loop(_map,function(_value,_key,_xmap){\n                _xmap[_key] = _value+'px';\n            });\n        };\n        return function(_isok){\n            if (this.__image.src==_g._$BLANK_IMAGE) return;\n            this._$dispatchEvent('onafterimageload',{\n                parent:this.__mbox,\n                loaded:_isok\n            });\n            if (!_isok) return;\n            // calculate position\n            var _pos = this.__doCalImagePosition({\n                    width:this.__image.width,\n                    height:this.__image.height\n                },{\n                    width:this.__mbox.clientWidth,\n                    height:this.__mbox.clientHeight\n                }),\n                _max = {\n                    width:_pos.width,\n                    height:_pos.height\n                };\n            this.__sopt.max = {\n                width:_pos.width,\n                height:_pos.height\n            };\n            this.__ratio = _pos.ratio;\n            delete _pos.ratio;\n            _doAppendUnit(_pos);\n            // build image\n            this.__cbox = _e._$create('div');\n            _pos.position = 'absolute';\n            _e._$style(this.__cbox,_pos);\n            this.__mbox.appendChild(this.__cbox);\n            _u._$forEach(\n                [new Image(),new Image()],\n                function(_img,_index){\n                    _imgsize.zIndex = 100+_index;\n                    _e._$style(_img,_imgsize);\n                    this.__cbox.appendChild(_img);\n                    _img.src = this.__image.src;\n                    if (_index==0){\n                        _e._$setStyle(_img,'opacity',0.3);\n                    }\n                    _img.draggable = !1;\n                },this\n            );\n            var _event = {\n                ratio:this.__ratio,\n                parent:this.__mbox\n            };\n            this._$dispatchEvent('onafterimageshow',_event);\n            // build resizer\n            if (_event.value instanceof _i._$$Resizer){\n                this.__resizer = _event.value;\n            }else{\n                var _options = _u._$merge(\n                    this.__sopt,\n                    _event.value\n                );\n                this.__sopt.parent = this.__cbox;\n                this.__resizer = _i._$$Resizer._$allocate(_options);\n            }\n            this.__resizer._$batEvent(this.__ropt);\n            this.__onClipping(this.__resizer._$getResizeBox());\n        };\n    })();\n    /**\n     * 图片裁剪\n     * \n     * @protected\n     * @method module:util/clipper/clipper._$$Clipper#__onClipping\n     * @param  {Object} arg0 - 裁剪信息\n     * @return {Void}\n     */\n    _pro.__onClipping = function(_event){\n        // sync clip image\n        var _img = this.__cbox.getElementsByTagName('IMG')[1],\n            _crp = [_event.top+'px',_event.left+_event.width+'px',\n                    _event.top+_event.height+'px',_event.left+'px'];\n        _e._$setStyle(_img,'clip','rect('+_crp.join(' ')+')');\n        // sync preview show\n        _u._$forIn(\n            this.__pbox,\n            function(_conf){\n                this.__doPreviewClip(_conf,_event);\n            },this\n        );\n        _event.ratio = this.__ratio;\n        this._$dispatchEvent('onclipchange',_event);\n    };\n    /**\n     * 预览图片\n     * \n     * @protected\n     * @method module:util/clipper/clipper._$$Clipper#__doPreviewClip\n     * @param  {Object} arg0 - 预览配置\n     * @param  {Object} arg1 - 裁剪信息\n     * @return {Void}\n     */\n    _pro.__doPreviewClip = function(_conf,_box){\n        if (!_box){\n            _box = this.__resizer._$getResizeBox();\n        }\n        var _pos = this.__doCalClipPosition(_box,_conf);\n        _conf.clip = {\n            top:_pos.top,\n            left:_pos.left,\n            width:_conf.width,\n            height:_conf.height,\n            scale:_pos.width/this.__image.width\n        };\n        var _img = _e._$get(_conf.img)||new Image(),\n            _style = {\n                position:'absolute',\n                top:0-_pos.top+'px',\n                left:0-_pos.left+'px',\n                width:_pos.width+'px',\n                height:_pos.height+'px'\n            };\n        _e._$style(_img,_style);\n        if (!_conf.img){\n            _conf.img = _e._$id(_img);\n            _e._$get(_conf.box).appendChild(_img);\n            _img.src = this.__image.src;\n        }\n    };\n    /**\n     * 设置图片地址\n     * \n     * @method module:util/clipper/clipper._$$Clipper#_$setURL\n     * @param  {String} arg0 - 图片地址\n     * @return {Void}\n     */\n    _pro._$setURL = function(_url){\n        if (!_url) return;\n        // do clear\n        this.__doClearResizer();\n        this.__doClearPreview(!0);\n        // do check\n        this._$dispatchEvent('onbeforeimageload',{\n            parent:this.__mbox\n        });\n        this.__image.src = _url;\n    };\n    /**\n     * 添加预览容器节点\n     * \n     * @method module:util/clipper/clipper._$$Clipper#_$addPreview\n     * @param  {String|Node} arg0 - 预览容器节点\n     * @return {Void}\n     */\n    _pro._$addPreview = function(_box){\n        var _box = _e._$get(_box);\n        if (!_box) return;\n        var _id = _e._$id(_box),\n            _width = _box.clientWidth,\n            _height = _box.clientHeight;\n        this.__pbox[_id] = {\n            box:_id,\n            width:_width,\n            height:_height,\n            ratio:_width/_height\n        };\n        if (!!this.__resizer){\n            this.__doPreviewClip(this.__pbox[_id]);\n        }\n    };\n    /**\n     * 删除预览视图\n     * \n     * @method module:util/clipper/clipper._$$Clipper#_$delPreview\n     * @param  {String}  arg0 - 标识\n     * @param  {Boolean} arg1 - 是否保留最终状态\n     * @return {Void}\n     */\n    _pro._$delPreview = function(_id,_keep){\n        var _map = this.__pbox[_id];\n        if (!!_map&&!_keep)\n            _e._$remove(_map.img);\n        delete this.__pbox[_id];\n    };\n    /**\n     * 取裁剪结果\n     * \n     * @method module:util/clipper/clipper._$$Clipper#_$getClipResult\n     * @param  {String} arg0 - 预览标识\n     * @return {Object}        裁剪结果\n     */\n    _pro._$getClipResult = function(_id){\n        var _conf = this.__pbox[_id];\n        // dump one\n        if (!!_conf){\n            return _conf.clip;\n        }\n        // dump all\n        var _result = {};\n        _u._$forIn(\n            this.__pbox,function(_conf,_key){\n                _result[_key] = _conf.clip;\n            }\n        );\n        return _result;\n    };\n    /**\n     * 更新裁剪区域\n     * \n     * @method module:util/clipper/clipper._$$Clipper#_$update\n     * @param  {Object} arg0 - 裁剪信息\n     * @return {Void}\n     */\n    _pro._$update = function(_info){\n        if (!!this.__resizer){\n            this.__resizer._$update(_info);\n        }\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/clipper/demo/clipper.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test clipper</title>\n    <meta charset=\"utf-8\"/>\n    <style>\n      *{border:0;padding:0;margin:0;}\n      html,body{width:100%;height:100%;}\n      .test{position:absolute;top:30%;left:20%;padding:20px;overflow:hidden;}\n      .box{border:1px solid #aaa;}\n      .mbox{position:relative;float:left;width:500px;height:500px;margin-right:-500px;}\n      .prev{margin-left:500px;padding-left:20px;}\n      .pbox{position:relative;margin-bottom:10px;overflow:hidden;}\n      .pbox-0{width:80px;height:80px;}\n      .pbox-1{width:120px;height:120px;}\n      .pbox-2{width:200px;height:200px;}\n    </style>\n  </head>\n  <body>\n    <div class=\"test\">\n      <div class=\"box mbox\" id=\"clip-main\"></div>\n      <div class=\"prev\">\n        <div class=\"box pbox pbox-0\" id=\"clip-preview-0\"></div>\n        <div class=\"box pbox pbox-1\" id=\"clip-preview-1\"></div>\n        <div class=\"box pbox pbox-2\" id=\"clip-preview-2\"></div>\n      </div>\n    </div>\n    <p><input type=\"button\" value=\"查看裁剪信息\" id=\"abc\"/></p>\n    <div id=\"result\"></div>\n    <script src=\"../../../define.js\"></script>\n    <script>\n      define([\n          'base/element',\n          'base/event',\n          'base/util',\n          'util/clipper/clipper'\n      ],function(_e,_v,_u,_t){\n          \n          var _clipper = _t._$$Clipper._$allocate({\n              url:'./1.jpg',\n              mbox:'clip-main',\n              pbox:[\n                  'clip-preview-0',\n                  'clip-preview-1',\n                  'clip-preview-2'\n              ],\n              lock:!0,\n              size:{\n                  ratio:1,\n                  width:80\n              }\n          });\n          \n          _v._$addEvent(\n              'abc','click',function(){\n                  var _result = [];\n                  _u._$forIn(\n                      _clipper._$getClipResult(),\n                      function(_inf,_id){\n                          _result.push('<p>'+_id+':'+JSON.stringify(_inf)+'</p>');\n                      }\n                  );\n                  _e._$get('result').innerHTML = _result.join('');\n              }\n          );\n          \n          \n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/clock/clock.js",
    "content": "/*\n * ------------------------------------------\n * 时钟算法实现文件\n * @version  1.0\n * @author   xiejin(hzxiejin@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/clock/clock */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'base/util',\n    'util/event'\n],function(NEJ,_k,_e,_v,_u,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 时间算法\n     *\n     * 结构举例\n     * ```html\n     * <div class=\"ztime js-clock\">\n     *   <select class=\"zper js-ztag\" size=\"2\">\n     *       <option value=\"A.M.\" selected>A.M.</option>\n     *       <option value=\"P.M.\">P.M.</option>\n     *   </select>\n     *   <input type=\"text\" id=\"z-hour\" class=\"js-ztag\"><div class=\"sep\">:</div>\n     *   <input type=\"text\" id=\"z-minute\" class=\"js-ztag\"><div class=\"sep\">:</div>\n     *   <input type=\"text\" id=\"z-second\" class=\"js-ztag\">\n     *   <div class=\"zbtn-list\">\n     *       <button class=\"js-ztag\" id=\"ztime-add\">&#9650;</button>\n     *       <button class=\"js-ztag\" id=\"ztime-minus\">&#9660;</button>\n     *   </div>\n     * </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/clock/clock'\n     * ],function(_t){\n     *     // 分配时间功能\n     *     var _clock = _t._$$Clock._$allocate({\n     *         cnxt:'ztime-minus',\n     *         cprv:'ztime-add',\n     *         hour:'z-hour',\n     *         minute:'z-minute',\n     *         second:'z-second',\n     *         format:'12'\n     *     });\n     *\n     * });\n     * ```\n     *\n     * @class    module:util/clock/clock._$$Clock\n     * @extends  module:util/event._$$EventTarget\n     *\n     * @param    {Object}      config   - 可选配置参数\n     * @property {String|Node} cnxt     - 减少时间按钮节点\n     * @property {String|Node} cprv     - 增加时间按钮节点\n     * @property {String|Node} hour     - 小时输入节点\n     * @property {String|Node} minute   - 分钟输入节点\n     * @property {String|Node} second   - 秒输入节点\n     * @property {String|Node} per      - 时段选择节点\n     * @property {Date}        date     - 显示日期，默认为当前时间\n     * @property {Number}      format   - 时制，默认为24时制\n     */\n\n    _p._$$Clock = _k._$klass();\n    _pro = _p._$$Clock._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/clock/clock._$$Clock#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        // init event\n        // TODO delegate event\n        this.__hnode = _e._$get(_options.hour);\n        this.__mnode = _e._$get(_options.minute);\n        this.__snode = _e._$get(_options.second);\n        this.__pnode = _e._$get(_options.per);\n        this.__cnxt  = _e._$get(_options.cnxt);\n        this.__cprv  = _e._$get(_options.cprv);\n        this.__doInitDomEvent([[\n            this.__cnxt,'click',\n            this.__onTimeChange._$bind(this,-1)\n        ],[\n            this.__cprv,'click',\n            this.__onTimeChange._$bind(this, 1)\n        ],[\n            this.__hnode,'input',\n            this.__onInput._$bind(this,0)\n        ],[\n            this.__mnode,'input',\n            this.__onInput._$bind(this,1)\n        ],[\n            this.__snode,'input',\n            this.__onInput._$bind(this,2)\n        ],[\n            this.__hnode,'click',\n            this.__onSelect._$bind(this)\n        ],[\n            this.__mnode,'click',\n            this.__onSelect._$bind(this)\n        ],[\n            this.__snode,'click',\n            this.__onSelect._$bind(this)\n        ]]);\n        this.__flag = this.__hnode;\n        this.__temp = [this.__hnode.value,this.__mnode.value,this.__snode.value];\n        this._$setClock(_options.date||(new Date()));\n        this._$setFormat(_options.format);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/clock/clock._$$Clock#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n    };\n    /**\n     * 同步时间显示\n     *\n     * @protected\n     * @method module:util/clock/clock._$$Clock#__doSyncTimeShow\n     * @return {Void}\n     */\n    _pro.__doSyncTimeShow = function(){\n        if(this.__format == 12){\n            if(this.__hour > 11){\n                if(this.__hour > 21){\n                    this.__hnode.value = this.__hour - 12;\n                }else{\n                    this.__hnode.value = '0' + (this.__hour - 12);\n                }\n                this.__pnode.value = 'P.M.';\n            }\n        }else{\n            this.__hnode.value = this.__hour;\n        }\n        this.__mnode.value = this.__minute;\n        this.__snode.value = this.__second;\n    };\n    /**\n     * 输入框被选择触发事件\n     *\n     * @protected\n     * @method module:util/clock/clock._$$Clock#__onSelect\n     * @param  {Event} arg0 - 事件对象\n     * @return {void}\n     */\n    _pro.__onSelect = function(_event){\n        var _target = _v._$getElement(_event);\n        this.__flag = _target;\n        _target.select();\n    };\n    /**\n     * 输入框输入触发事件\n     *\n     * @protected\n     * @method module:util/clock/clock._$$Clock#__onInput\n     * @param  {Number} arg0 - 输入框标记\n     * @param  {Event}  arg1 - 事件对象\n     * @return {void}\n     */\n    _pro.__onInput = (function(){\n        var _map = [23,59,59],\n            _reg = /^\\d{1,2}$/;\n        return function(_type,_event){\n            var _target = _v._$getElement(_event),\n                _tempv  = this.__temp[_type],\n                _str    = '' + _target.value,\n                _flag   = !_reg.test(_str),\n                _flag2  = _str === '';\n            if (!_flag2){\n                if(parseInt(_target.value,10) > _map[_type] || _flag){\n                    _target.value = _tempv;\n                }\n                if(_type == 0 && this.__format == 12 && (parseInt(_target.value,10) > 11 || _flag)){\n                    _target.value = _tempv;\n                }\n            }\n            this.__temp[_type] = _target.value;\n        };\n    })();\n\n    /**\n     * 时间修改触发事件\n     *\n     * @protected\n     * @method module:util/clock/clock._$$Clock#__onTimeChange\n     * @param  {Number} arg0 - 输入框标记\n     * @param  {Event}  arg1 - 事件对象\n     * @return {void}\n     */\n    _pro.__onTimeChange = function(_index,_event){\n        var _node = this.__flag,\n            _per = this.__format,\n            _temp = 0;\n        if(_node.value){\n            _temp = parseInt(_node.value,10) + _index;\n        }else{\n            _node.value = 0;\n        }\n        if (_temp < 10 && _temp >-1){\n            _node.value = '0' + _temp;\n        }else{\n            _node.value = _temp;\n        }\n        if(_node.id == 'z-hour'){\n            if (_temp == _per){\n                _node.value = '00';\n            }else if(_temp == -1){\n                _node.value = '' + (_per - 1);\n            }\n            this.__hour = _node.value;\n            this.__temp[0] = '';\n        }else if(_node.id == 'z-minute' || _node.id == 'z-second'){\n            if(_temp == 60){\n                _node.value = '00';\n            }else if(_temp == -1){\n                _node.value = '59';\n            }\n            if(_node.id == 'z-minute'){\n                this.__minute = _node.value;\n                this.__temp[1] = '';\n            }\n            if(_node.id == 'z-second'){\n                this.__second = _node.value;\n                this.__temp[2] = '';\n            }\n        }\n    };\n    /**\n     * 设置时间\n     *\n     * 脚本举例\n     * ```javascript\n     * _clock._$setClock('11:11:11');\n     * ```\n     *\n     * @method module:util/clock/clock._$$Clock#_$setClock\n     * @param  {String|Date} arg0 - 时间\n     * @return {Void}\n     */\n    _pro._$setClock = (function(){\n        var _setTime = function(_date,_obj){\n            _obj.h = _date.getHours();\n            _obj.m = _date.getMinutes();\n            _obj.s = _date.getSeconds();\n            return _obj;\n        };\n        var _var2time = function(_time){\n            var _date = _time,\n                _obj = {};\n            if (_u._$isString(_time)){\n                var _list = _time.split(':');\n                _obj.h = _list[0];\n                _obj.m = _list[1];\n                _obj.s = _list[2];\n            }\n            if (!_u._$isDate(_time)){\n                _date = new Date(_time);\n                _obj = _setTime(_date,_obj);\n            }else{\n                _obj = _setTime(_date,_obj);\n            }\n            return _obj;\n        };\n        return function(_time){\n            _time = _var2time(_time);\n            this.__hour = _time.h < 10 ? '0' + _time.h : _time.h;\n            this.__minute = _time.m < 10 ? '0' + _time.m : _time.m;\n            this.__second = _time.s < 10 ? '0' + _time.s : _time.s;\n            this.__doSyncTimeShow();\n        };\n    })();\n    /**\n     * 取当前选择时间\n     *\n     * 脚本举例\n     * ```javascript\n     * _clock._$getClock();\n     * ```\n     *\n     * @method module:util/clock/clock._$$Clock#_$getClock\n     * @return {Object} 当前选择时间\n     */\n    _pro._$getClock = function(){\n        var _clock = {\n            h:parseInt(this.__hour,10),\n            m:parseInt(this.__minute,10),\n            s:parseInt(this.__second,10)\n        };\n        _u._$forEach(this.__temp,function(_temp,_index){\n            if (!!_temp){\n                if (_index==0){\n                    _clock.h = _temp;\n                }else if(_index==1){\n                    _clock.m = _temp;\n                }else{\n                    _clock.s = _temp;\n                }\n            }\n        });\n        if(this.__format == 12){\n            _clock.p = this.__pnode.value;\n            if(_clock.p == 'A.M.' && _clock.h > 11) {\n                _clock.h -= 12;\n            } else if(_clock.p == 'P.M.' && _clock.h < 12) {\n                _clock.h += 12;\n            }\n        }\n        _u._$forIn(_clock,function(_v,_k){\n            if (parseInt(_v,10)<10){\n                _clock[_k] = '0' + parseInt(_v,10);\n            }\n        })\n        return _clock;\n    };\n    /**\n     * 设置时制\n     *\n     * 脚本举例\n     * ```javascript\n     * _clock._$setFormat(12);\n     * ```\n     *\n     * @method module:util/clock/clock._$$clock#_$setFormat\n     * @param  {Number} arg0 - 时制,默认24\n     * @return {void}\n     */\n    _pro._$setFormat = function(_format){\n        this.__format = (_format && _format == 12)? 12 : 24;\n        if(this.__format == 12){\n            this.__pnode.style.display = 'block';\n            this.__doSyncTimeShow();\n        }\n    };\n\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/color/color.js",
    "content": "/*\n * ------------------------------------------\n * 颜色辅助方法实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/color/color */\nNEJ.define([\n    'base/global',\n    'base/util'\n],function(NEJ,_u,_p,_o,_f,_r){\n    /**\n     * 判断色值是否合法\n     *\n     * @method module:util/color/color._$isColor\n     * @param  {String} arg0 - 颜色值\n     * @return {Boolean}       是否合法\n     */\n    _p._$isColor = (function(){\n        var _reg = /^#(?:[0-9a-f]{3}){1,2}$/i;\n        return function(_color){\n            return _reg.test(_color);\n        };\n    })();\n    /**\n     * 判断是否完整格式的颜色值，如#ffffff\n     *\n     * @method module:util/color/color._$isFullColor\n     * @param  {String} arg0 - 颜色值\n     * @return {Boolean}       是否完整格式\n     */\n    _p._$isFullColor = (function(){\n        var _reg = /^#[0-9a-f]{6}$/i;\n        return function(_color){\n            return _reg.test(_color);\n        };\n    })();\n    /**\n     * 提取色值的RGB信息\n     *\n     * @method module:util/color/color._$color2rgb\n     * @param  {String} arg0 - 颜色值，#ffffff或者#fff\n     * @return {Object}        RGB信息，{r:23,g:25,b:67}\n     */\n    _p._$color2rgb = (function(){\n        var _doExpand = function(_value,_index,_list){\n            _list[_index] += _value;\n        };\n        return function(_color){\n            if (!_p._$isColor(_color))\n                return null;\n            _color = _color.substr(1);\n            // #fff -> #ffffff\n            if (_color.length==3){\n                var _arr = _color.split('');\n                _u._$forEach(_arr,_doExpand);\n                _color = _arr.join('');\n            }\n            return {\n                r:parseInt(_color.substr(0,2),16),\n                g:parseInt(_color.substr(2,2),16),\n                b:parseInt(_color.substr(4,2),16)\n            };\n        };\n    })();\n    /**\n     * RGB色值转颜色字符串\n     *\n     * @method module:util/color/color._$rgb2color\n     * @param  {Object} arg0 - RGB信息，如{r:23,g:24,b:35}\n     * @return {String}        颜色字符串，如#fdcdfc\n     */\n    _p._$rgb2color = (function(){\n        var char = '0123456789abcdef';\n        function toHex(n) {\n            n = parseInt(n,10);\n            if (isNaN(n)) return '00';\n            n = Math.max(0,Math.min(n,255));\n            return char.charAt((n-n%16)/16)+char.charAt(n%16);\n        }\n        return function(rgb){\n            return '#'+toHex(rgb.r)+toHex(rgb.g)+toHex(rgb.b);\n        };\n    })();\n    /**\n     * RGB色值转HLS色值\n     *\n     * @method module:util/color/color._$rgb2hsl\n     * @param  {Object} arg0 - RGB信息，如{r:23,g:24,b:35}\n     * @return {Object}        HSL信息，如{h:0.7,l:0.6,s:0.9}\n     */\n    _p._$rgb2hsl = function(rgb){\n        var r = rgb.r,\n            g = rgb.g,\n            b = rgb.b;\n        r /= 255, g /= 255, b /= 255;\n        var max = Math.max(r, g, b),\n            min = Math.min(r, g, b);\n        var h,s,\n            d = max-min,\n            l = (max+min)/2;\n        if(d==0){\n            // achromatic\n            h = s = 0;\n        }else{\n            var d = max-min;\n            s = l>0.5 ? d/(2-max-min) : d/(max+min);\n            switch(max){\n                case r: h = (g-b)/d+(g<b?6:0); break;\n                case g: h = (b-r)/d+2; break;\n                case b: h = (r-g)/d+4; break;\n            }\n            h /= 6;\n        }\n        return { h:h,s:s,l:l };\n    };\n    /**\n     * HSL色值转RGB色值\n     *\n     * @param  {Object} arg0 - HSL信息，{h:0.7,l:0.6,s:0.9}\n     * @return {Object}        RGB信息，如{r:23,g:24,b:35}\n     */\n    _p._$hsl2rgb = (function(){\n        var hue2rgb = function(p, q, t){\n            if(t<0) t += 1;\n            if(t>1) t -= 1;\n            if(t<1/6) return p+(q-p)*6*t;\n            if(t<1/2) return q;\n            if(t<2/3) return p+(q-p)*(2/3-t)*6;\n            return p;\n        };\n        return function(hsl){\n            var red, green, blue;\n            if(hsl.s==0){\n                // achromatic\n                red = green = blue = hsl.l;\n            }else{\n                var l = hsl.l,\n                    s = hsl.s,\n                    h = hsl.h;\n                var q = l<0.5?(l*(1+s)):(l+s-l*s),\n                    p = 2*l-q;\n                red = hue2rgb(p, q, h + 1/3);\n                green = hue2rgb(p, q, h);\n                blue = hue2rgb(p, q, h - 1/3);\n            }\n            return {\n                r:Math.round(red*255),\n                g:Math.round(green*255),\n                b:Math.round(blue*255)\n            };\n        };\n    })();\n    /**\n     * HSL色值转颜色字符串\n     *\n     * @method module:util/color/color._$hsl2color\n     * @param  {Object} arg0 - HSL信息，{h:0.7,l:0.6,s:0.9}\n     * @return {String}        颜色字符串，如#dddfdc\n     */\n    _p._$hsl2color = function(hsl){\n        return _p._$rgb2color(_p._$hsl2rgb(hsl));\n    };\n    /**\n     * RGB颜色串转HSL色值\n     *\n     * @method module:util/color/color._$color2hsl\n     * @param  {String} arg0 - 颜色串\n     * @return {Object}        HSL信息，如{h:0.7,l:0.6,s:0.9}\n     */\n    _p._$color2hsl = function(_color){\n        return _p._$rgb2hsl(_p._$color2rgb(_color));\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.c'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/color/demo/color.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - 颜色转换</title>\n    <meta charset=\"utf-8\" />\n  </head>\n  <body>\n    <p><input type=\"text\" id=\"a\"/></p>\n    <p><textarea id=\"b\"></textarea></p>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            '../color.js'\n        ],function(x){\n//            var color = '#fdc';\n//            var rgb = x._$color2rgb(color);\n//            console.log('color -> rgb');\n//            console.log(rgb);\n//            console.log('rgb -> color');\n//            console.log(x._$rgb2color(rgb));\n//            var hsl = x._$rgb2hsl(rgb);\n//            console.log('rgb -> hsl');\n//            console.log(hsl);\n//            console.log('hsl -> color');\n//            console.log(x._$hsl2color(hsl));\n//            console.log('color -> hsl');\n//            console.log(x._$color2hsl(color));\n\n            var rgb = {r:1,g:161,b:237};\n            var hsl = x._$rgb2hsl(rgb);\n            console.log('rgb:'+JSON.stringify(rgb));\n            console.log('hsl:'+JSON.stringify(hsl));\n            console.log('hsl->rgb:'+JSON.stringify(x._$hsl2rgb(hsl)));\n\n            console.log('rgb->color:'+x._$rgb2color(rgb));\n            console.log('rgb->hsl->color:'+x._$hsl2color(x._$rgb2hsl(rgb)));\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/counter/counter.js",
    "content": "/*\n * ------------------------------------------\n * 输入框计数器接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/counter/counter */\nNEJ.define([\n    'base/global',\n    'base/element',\n    'base/event',\n    'base/util',\n    'base/chain',\n    '{platform}counter.js'\n],function(NEJ,_e,_v,_u,_x,_h,_p,_o,_f,_r){\n    /**\n     * 输入框计数器，使用属性设置输入的总长度限制，\n     * 以下两个属性只能同时设置一个，maxlength优先级高于data-max-length\n     *\n     * | 属性名 | 描述 |\n     * | :---   | :--- |\n     * | data-max-length | 输入长度必须小于此设置，一个中文算两个字符，适用于text/textarea |\n     * | maxlength       | 输入长度必须小于此设置，一个中文算一个字符，适用于text/textarea |\n     *\n     * 结构举例：\n     * ```html\n     * <input type=\"text\" id=\"input-id-0\" maxlength=\"100\"/>\n     * <input type=\"text\" id=\"input-id-1\" data-max-length=\"100\"/>\n     * <textarea id=\"textarea-id-0\" maxlength=\"100\"></textarea>\n     * <textarea id=\"textarea-id-1\" data-max-length=\"100\"></textarea>\n     * ```\n     *\n     * 脚本举例：\n     * ```javascript\n     * NEJ.define([\n     *     'util/counter/counter'\n     * ],function(_e){\n     *     // 使用属性\n     *     _e._$counter('input-id-0',{\n     *         onchange:function(_event){\n     *                // 自定义提示内容\n     *                _event.value = '还可输入'+_event.delta+'字';\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/counter/counter._$counter\n     * @param    {String|Node} arg0    - 输入节点\n     * @param    {Object}      arg1    - 配置参数\n     * @property {String}      nid     - 显示提示信息节点标识\n     * @property {Number}      max     - 最大字数限制，优先级大于标签上配置的属性，一个中文算一个字符，默认100个字符\n     * @property {String}      clazz   - 计数器显示样式\n     * @property {Function}   onchange - 字数变化触发回调，{input:'xx',length:2,delta:98}\n     * @return   {Void}\n     */\n    /**\n     * @method CHAINABLE._$counter\n     * @see module:util/counter/counter._$counter\n     */\n    _p._$counter = (function(){\n        var _reg0 = /[\\r\\n]/gi,\n            _cache = {}; // {id:{max:123,id:'xxx',onchange:function,onlength:function}}\n        // calculate string length\n        var _doLength = function(_str){\n            return _h.__length(_str);\n        };\n        // input change\n        var _onChange = function(_id){\n            var _conf  = _cache[_id],\n                _node1 = _e._$get(_id),\n                _node2 = _e._$get(_conf.xid);\n            if (!_node1||!_conf) return;\n            var _event = {\n                input:_node1.value\n            };\n            _event.length = _conf.onlength(_event.input);\n            _event.delta = _conf.max-_event.length;\n            _conf.onchange(_event);\n            _node2.innerHTML = _event.value||('剩余'+Math.max(0,_event.delta)+'个字');\n        };\n        return function(_element,_options){\n            var _id = _e._$id(_element);\n            if (!_id||!!_cache[_id]) return;\n            // check config\n            var _conf = _u._$merge({},_options);\n            _conf.onchange = _conf.onchange||_f;\n            _conf.onlength = _doLength;\n            if (!_conf.max){\n                var _max1 = parseInt(_e._$attr(_id,'maxlength')),\n                    _max2 = parseInt(_e._$dataset(_id,'maxLength'));\n                _conf.max = _max1||_max2||100;\n                if (!_max1&&!!_max2) _conf.onlength = _u._$length;\n            }\n            _cache[_id] = _conf;\n            // add listener\n            _v._$addEvent(_id,'input',_onChange._$bind(null,_id));\n            // init left counter show\n            var _node = _e._$wrapInline(_id,{\n                nid:_conf.nid||'js-counter',\n                clazz:_conf.clazz\n            });\n            _conf.xid = _e._$id(_node);\n            _onChange(_id);\n        };\n    })();\n    // for chainable method\n    _x._$merge(_p);\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.e'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/counter/demo/counter.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - 计数器</title>\n    <meta charset=\"utf-8\" />\n  </head>\n  <body>\n    <p><input type=\"text\" id=\"a\"/></p>\n    <p><textarea id=\"b\"></textarea></p>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            '../counter.js'\n        ],function(_e){\n            _e._$counter('a');\n            _e._$counter('b');\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/counter/platform/counter.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   \n * ------------------------------------------\n */\nNEJ.define([\n    'base/platform'\n],function(_p){\n    /**\n     * 取字符串长度\n     * @param  {String} 字符串\n     * @return {Number} 字符串长度\n     */\n    _p.__length = (function(){\n        var _reg = /(\\r\\n|\\r|\\n)/g;\n        return function(_content){\n            return (_content||'').replace(_reg,'**').length;\n        };\n    })();\n    \n    return _p;\n});"
  },
  {
    "path": "src/util/counter/platform/counter.patch.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   \n * ------------------------------------------\n */\nNEJ.define([\n    './counter.js'\n],function(_h){\n    // for ie\n    NEJ.patch('TR',function(){\n        /**\n         * 取字符串长度\n         * @param  {String} 字符串\n         * @return {Number} 字符串长度\n         */\n        _h.__length = function(){\n            return (_event.args[0]||'').length;\n        };\n    });\n    \n    return _h;\n});"
  },
  {
    "path": "src/util/counter/test/counter.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>counter测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n        <style type=\"text/css\">\n        .box{width:300px;height:50px;display:block;}\n        </style>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit xdr test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <div class=\"box\"><input type=\"text\" id=\"input-id-0\" maxlength=\"100\"/></div>\n        <div class=\"box\"><input type=\"text\" id=\"input-id-1\" data-max-length=\"100\"/></div>\n        <div class=\"box\"><textarea id=\"textarea-id-0\" maxlength=\"100\"></textarea></div>\n        <div class=\"box\"><textarea id=\"textarea-id-1\" data-max-length=\"100\"></textarea></div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./counter.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/counter/test/counter.test.js",
    "content": "NEJ.define(['util/counter/counter'],function(){\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v');\n    test('counter',function(){\n        expect(0);\n        _e._$counter('input-id-0',{\n            onchange:function(_event){\n             // 自定义提示内容\n             _event.value = '还可输入input'+_event.delta+'字';\n            }\n        });\n        _e._$counter('input-id-1',{\n            onchange:function(_event){\n             // 自定义提示内容\n             _event.value = '还可输入input'+_event.delta+'字';\n            }\n        });\n\n        _e._$counter('textarea-id-0',{\n            onchange:function(_event){\n             // 自定义提示内容\n             _event.value = '还可输入textarea'+_event.delta+'字';\n            }\n        });\n\n        _e._$counter('textarea-id-1',{\n            onchange:function(_event){\n             // 自定义提示内容\n             _event.value = '还可输入textarea'+_event.delta+'字';\n            }\n        });\n    });\n});"
  },
  {
    "path": "src/util/cursor/cursor.js",
    "content": "/*\n * ------------------------------------------\n * 输入框光标相关接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/cursor/cursor */\nNEJ.define([\n    'base/global',\n    'base/element',\n    'base/util',\n    'base/chain',\n    '{platform}cursor.js'\n],function(NEJ,_e,_u,_x,_h,_p,_o,_f,_r){\n    var _y = {};\n    /**\n     * 设置/获取光标位置在TEXTAREA中的位置\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'util/cursor/cursor'\n     *   ],function(_e){\n     *       // 设置光标选中内容\n     *       _e._$cursor('xxx',{start:5,end:10});\n     *       // 设置光标位置\n     *       _e._$cursor('xxx',8);\n     *\n     *       // 获取光标位置\n     *       // _position.start 光标起始位置\n     *       // _position.end   光标结束位置\n     *       var _position = _e._$cursor('xxx');\n     *   });\n     * ```\n     *\n     * @method   module:util/cursor/cursor._$cursor\n     * @param    {String|Node}   arg0  - TEXTAREA或者INPUT节点\n     * @param    {Number|Object} arg1  - 待设置光标的位置，如果起始位置和结束位置一致则输入数值即可\n     * @property {Number}        start - 起始位置\n     * @property {Number}        end   - 结束位置，没有end则表示与start相同\n     * @return   {Object}                光标位置，{start:0,end:10}\n     */\n    /**\n     * @method CHAINABLE._$cursor\n     * @see module:util/cursor/cursor._$cursor\n     */\n    _p._$cursor =\n    _y._$cursor = function(_textarea,_options){\n        _textarea = _e._$get(_textarea);\n        if (!_textarea){\n            return {start:0,end:0};\n        }\n        // position\n        if (_u._$isNumber(_options)){\n            _options = {\n                start:_options,\n                end:_options\n            };\n        }\n        if (_options!=null){\n            if (_options.end==null){\n                _options.end = _options.start||0;\n            }\n            _h.__setCursorPosition(_textarea,_options);\n        }else{\n            _options = _h.__getCursorPosition(_textarea);\n        }\n        return _options;\n    };\n    /**\n     * 取输入框光标相对于输入框左上角像素位置\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/cursor/cursor'\n     * ],function(_e){\n     *     // 返回 {top:10,left:20,width:30,height:20}\n     *     var _cord = _e._$coordinate('input-id');\n     * \n     *     // 返回 {top:10,left:20,width:30,height:20}\n     *     var _cord = _e._$coordinate('textarea-id');\n     * });\n     * ``\n     * \n     * @method module:util/cursor/cursor._$coordinate\n     * @param  {Node|String} arg0 - 输入节点\n     * @return {Object}             光标像素坐标，如 {top:10,left:20,width:30,height:20}\n     */\n    /**\n     * @method CHAINABLE._$coordinate\n     * @see module:util/cursor/cursor._$coordinate\n     */\n    _p._$coordinate = \n    _y._$coordinate = function(_input){\n        _input = _e._$get(_input);\n        if (!_input){\n            return {\n                top:0,\n                left:0,\n                width:0,\n                height:0\n            };\n        }\n        return _h.__getCursorPXPosition(_input);\n    };\n    /**\n     * 取输入框光标所在的行号\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/cursor/cursor'\n     * ],function(_e){\n     *     // 返回 1\n     *     var lineno = _e._$lineno('input-id');\n     *\n     *     // 返回 10\n     *     var lineno = _e._$lineno('textarea-id');\n     * });\n     * ``\n     *\n     * @method module:util/cursor/cursor._$lineno\n     * @param  {Node|String} arg0 - 输入节点\n     * @return {Number}             光标所在的行号，行号从 1 开始\n     */\n    /**\n     * @method CHAINABLE._$lineno\n     * @see module:util/cursor/cursor._$lineno\n     */\n    _p._$lineno =\n    _y._$lineno = function(_input){\n        var ipt = _e._$get(_input),\n            ret = _p._$cursor(ipt);\n        if (!ipt||!ret){\n            return 0;\n        }\n        return (ipt.value||'').substr(0,ret.start).split(/\\r\\n|\\r|\\n/).length;\n    };\n\n    // for chainable\n    _x._$merge(_y);\n    \n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.e'),_p);\n    }\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/cursor/demo/cursor.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - 计数器</title>\n    <meta charset=\"utf-8\" />\n    <script>\n      function log(msg){\n          var div = document.createElement('div');\n          div.innerHTML = msg;\n          document.body.appendChild(div);\n      }\n    </script>\n  </head>\n  <body>\n    <textarea id=\"abc\" style=\"width:300px;height:200px\" onclick=\"b();\"></textarea>\n    <input type=\"button\" value=\"show\" onclick=\"a();\"/>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            '../cursor.js'\n        ],function(_e){\n            var xx;\n            var tx = document.getElementById('abc');\n            tx.onbeforedeactivate = function(){\n                xx = _e._$cursor(tx);\n            };\n            window.a = function(){\n                var p = xx||_e._$cursor(tx),\n                    v = tx.value,\n                    t = '[表情]';\n                tx.value = v.substr(0, p.start)+t+ v.substring(p.end);\n                _e._$cursor(tx,p.start+ t.length);\n                xx = null;\n            };\n            window.b = function(){\n                log(_e._$lineno(tx));\n            };\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/cursor/platform/cursor.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   \n * ------------------------------------------\n */\nNEJ.define([\n    'base/element',\n    'base/platform'\n],function(_e,_m,_p,_o,_f,_r){\n    /**\n     * 设置光标位置\n     * @param  {String|Node} TEXTAREA节点\n     * @param  {Object}      光标的位置信息\n     * @return {Void}\n     */\n    _p.__setCursorPosition = function(_textarea,_position){\n        _textarea.selectionEnd = _position.end||0;\n        _textarea.selectionStart = _position.start||0;\n        _textarea.focus();\n    };\n    /**\n     * 取光标位置\n     * @param  {String|Node} TEXTAREA节点\n     * @return {Void}\n     */\n    _p.__getCursorPosition = function(_textarea){\n        // check focus\n        var act = null,\n            doc = _textarea.ownerDocument;\n        if (!!doc){\n            act = doc.activeElement;\n        }\n        if (act!=_textarea){\n            _textarea.focus();\n        }\n        // get position\n        return {\n            end:_textarea.selectionEnd,\n            start:_textarea.selectionStart\n        };\n    };\n    /**\n     * 取光标像素位置\n     * @param  {Node}   输入节点\n     * @return {Object} 光标像素位置\n     */\n    _p.__getCursorPXPosition = function(_input){\n        var _div = document.createElement('div');\n        _e._$style(_div,{\n            position:'absolute',\n            visibility:'hidden',\n            whiteSpace:'pre-wrap',\n            appearance:'textarea',\n            font:_e._$getStyle(_input,'font'),\n            display:_e._$getStyle(_input,'display'),\n            padding:_e._$getStyle(_input,'padding'),\n            wordWrap:_e._$getStyle(_input,'wordWrap'),\n            textAlign:_e._$getStyle(_input,'textAlign'),\n            letterSpacing:_e._$getStyle(_input,'letterSpacing'),\n            top:0,\n            left:0,\n            width:_input.clientWidth+'px',\n            height:_input.clientHeight+'px'\n        });\n        _div.innerText = _input.value;\n        var _span = document.createElement('span');\n        _div.appendChild(_span);\n        document.body.appendChild(_div);\n        var _ret = {\n            width:0,\n            top:_span.offsetTop,\n            left:_span.offsetLeft,\n            height:_span.offsetHeight\n        };\n        _e._$remove(_div);\n        return _ret;\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/cursor/platform/cursor.patch.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   \n * ------------------------------------------\n */\nNEJ.define([\n    './cursor.js',\n    'base/platform',\n    'base/element'\n],function(_h,_m,_e,_p,_o,_f,_r){\n    // TR 2.0 - IE 6\n    // TR 3.0 - IE 7\n    // TR 4.0 - IE 8\n    // TR 5.0 - IE 9\n    // TR 6.0 - IE 10\n    // TR 7.0 - IE 11\n    \n    // for ie\n    NEJ.patch('TR',function(){\n        /**\n         * 取光标像素位置\n         * @param  {Node}   输入节点\n         * @return {Object} 光标像素位置\n         */\n        _h.__getCursorPXPosition = function(_input){\n            _input.focus();\n            var _range = document.selection.createRange(),\n                _bpage = _e._$getPageBox(),\n                _offset = _e._$offset(_input);\n            return {\n                top:_range.boundingTop-_offset.y+_bpage.scrollTop,\n                left:_range.boundingLeft-_offset.x+_bpage.scrollLeft,\n                width:_range.boundingWidth,\n                height:_range.boundingHeight\n            };\n        };\n    });\n    // for ie8-\n    NEJ.patch('TR<=4.0',function(){\n        /**\n         * 设置光标位置\n         * @param  {String|Node} TEXTAREA节点\n         * @param  {Object}      光标的位置信息\n         * @return {Void}\n         */\n        _h.__setCursorPosition = function(_textarea,_position){\n            var _range = _textarea.createTextRange();\n            _range.collapse(!0);\n            _range.moveStart('character',_position.start);\n            _range.moveEnd('character',_position.end-_position.start);\n            _range.select();\n            _textarea.focus();\n        };\n        /**\n         * 取光标位置\n         * @param  {String|Node} TEXTAREA节点\n         * @return {Void}\n         */\n        _h.__getCursorPosition = function(_textarea){\n            var _range0 = document.selection.createRange();\n            // create in textarea object and match to document.selection\n            var _range1 = _textarea.createTextRange();\n            _range1.moveToBookmark(_range0.getBookmark());\n            // create textrange object for left amount of textarea & align them\n            var _range2 = _textarea.createTextRange();\n            _range2.collapse(!0);\n            _range2.setEndPoint(\"EndToStart\",_range1);\n            // dump start and end\n            var _start = _range2.text.length;\n            return {\n                start:_start,\n                end:_start+_range0.text.length\n            };\n        };\n    });\n    \n    return _h;\n});\n"
  },
  {
    "path": "src/util/cycler/cycler.js",
    "content": "/*\n * ------------------------------------------\n * 循环播放封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/cycler/cycler */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'base/util',\n    'util/event',\n    'util/page/simple'\n],function(NEJ,_k,_e,_v,_u,_t,_t0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 循环播放封装对象\n     *\n     * 结构举例\n     * ```html\n     * <div id=\"nbox\"></div>\n     * <ul id=\"pbox\">\n     *   <li>1</li>\n     *   <li>2</li>\n     *   <li>3</li>\n     * </ul>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/cycler/cycler'\n     * ],function(_t){\n     *     var _cycler = _t._$$Cycler._$allocate({\n     *         list:[\n     *             'http://xxxx.com/xxx.jpg',\n     *             'http://xxxx.com/xxx.jpg',\n     *             'http://xxxx.com/xxx.jpg'\n     *         ],\n     *         nbox:'nbox',\n     *         pbox:'pbox',\n     *         event:'click',\n     *         interval:5,\n     *         onchange:function(_index){\n     *             // 切换页面的回调，_index从1到3\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @class    module:util/cycler/cycler._$$Cycler\n     * @extends  module:util/event._$$EventTarget\n     *\n     * @param    {Object}      config   - 可选配置参数\n     * @property {Array}       list     - 图片地址列表\n     * @property {String|Node} nbox     - 图片容器节点\n     * @property {String|Node} pbox     - 页码索引容器节点\n     * @property {String}      event    - 页码切换事件名称\n     * @property {Number}      interval - 轮播时间间隔，单位秒，默认为2s\n     */\n    /**\n     * 图片切换事件\n     *\n     * @event module:util/cycler/cycler._$$Cycler#onchange\n     * @param {Number} event - 页码信息\n     */\n    _p._$$Cycler = _k._$klass();\n    _pro = _p._$$Cycler._$extend(_t._$$EventTarget);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:util/cycler/cycler._$$Cycler#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__popt = {\n            index:1,\n            onchange:this.__onPageChange._$bind(this)\n        };\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/cycler/cycler._$$Cycler#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__list = _options.list||[];\n        this.__nbox = _e._$get(_options.nbox);\n        this.__interval = (_options.interval||2)*1000;\n        var _list = _e._$getChildren(_options.pbox);\n        this.__popt.list  = _list;\n        this.__popt.total = _list.length;\n        this.__popt.event = _options.event;\n        this.__pager = _t0._$$PageSimple._$allocate(this.__popt);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/cycler/cycler._$$Cycler#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        _e._$remove(this.__image);\n        delete this.__nbox;\n        delete this.__image;\n        delete this.__popt.list;\n        this.__timer = window.clearTimeout(this.__timer);\n    };\n    /**\n     * 页面变化回调\n     *\n     * @protected\n     * @method   module:util/cycler/cycler._$$Cycler#__onPageChange\n     * @param    {Object} arg0  - 页码信息\n     * @property {Number} index - 页码信息\n     * @return   {Void}\n     */\n    _pro.__onPageChange = function(_event){\n        this.__timer = window.clearTimeout(this.__timer);\n        var _index = _event.index,\n            _url = this.__list[_index-1];\n        if (!!_url)\n            this._$setImage(_url);\n        this._$dispatchEvent('onchange',_index);\n    };\n    /**\n     * 去到下一页\n     *\n     * @protected\n     * @method module:util/cycler/cycler._$$Cycler#__onNextPage\n     * @return {Void}\n     */\n    _pro.__onNextPage = function(){\n        var _index = this.__pager._$getIndex(),\n            _total = this.__pager._$getTotal();\n        this.__pager._$setIndex((_index+1)%(_total+1));\n    };\n    /**\n     * 图片载入完成触发事件\n     *\n     * @protected\n     * @method module:util/cycler/cycler._$$Cycler#__onImageLoad\n     * @param  {Boolean} arg0 - 是否载入成功\n     * @return {Void}\n     */\n    _pro.__onImageLoad = function(_isok){\n        this.__timer = window.setTimeout(\n            this.__onNextPage._$bind(this),this.__interval);\n        _e._$setStyle(this.__imgbox,'opacity',1);\n    };\n    /**\n     * 设置图片\n     *\n     * 脚本举例\n     * ```javascript\n     * // 在回调里突然想换另外一张图片来展示\n     * _cycler._$setImage('http://abc.com/abc.jpg');\n     * ```\n     *\n     * @method module:util/cycler/cycler._$$Cycler#_$setImage\n     * @param  {String} arg0 - 图片地址\n     * @return {Void}\n     */\n    _pro._$setImage = (function(){\n        var _css = {\n            opacity:0,\n            transitionProperty:'opacity',\n            transitionDuration:'1s',\n            transitionTimingFunction:'ease-in-out'\n        };\n        var _doSetStyle = function(_value,_key){\n            _e._$setStyle(this.__imgbox,_key,_value);\n        };\n        return function(_url){\n            if (!!this.__image)\n                _e._$remove(this.__image);\n            if (!!this.__imgbox)\n                _e._$remove(this.__imgbox);\n            this.__image = new Image();\n            this.__imgbox = _e._$create('div');\n            _u._$forIn(_css,_doSetStyle,this);\n            if (_url.indexOf('.png') > -1){\n                _e._$setStyle(this.__image,'filter','progid:DXImageTransform.Microsoft.AlphaImageLoader (enabled=true)');\n            }\n            this.__imgbox.appendChild(this.__image);\n            this.__nbox.appendChild(this.__imgbox);\n            _v._$addEvent(this.__image,'load',\n                this.__onImageLoad._$bind(this,!0));\n            _v._$addEvent(this.__image,'error',\n                this.__onImageLoad._$bind(this,!1));\n            this.__image.src = _url;\n        };\n    })();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/cycler/test/cycler.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>cycler测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit cycler test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n\t\t<div id=\"nbox\"></div>\n\t\t<div id=\"pbox\">\n\t\t\t<a>1</a><a>2</a><a>3</a>\n\t\t</div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./cycler.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/cycler/test/cycler.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"cycler\");\n\n\tvar _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v'),\n        _p = _('nej.ut');\n\n\ttest('cycler test',function(){\n\t\t// stop();\n        expect(0);\n\t\t_p._$$Cycler._$allocate(\n\t\t{\n\t\t\tlist:['http://t1.gstatic.com/images?q=tbn:ANd9GcQrxfh6Z30dfii0p6XxH6wwuZ42dYTagoI24tybY2STiEpSPXvRzA',\n\t\t\t'http://t1.gstatic.com/images?q=tbn:ANd9GcQrxfh6Z30dfii0p6XxH6wwuZ42dYTagoI24tybY2STiEpSPXvRzA',\n            'http://t1.gstatic.com/images?q=tbn:ANd9GcQrxfh6Z30dfii0p6XxH6wwuZ42dYTagoI24tybY2STiEpSPXvRzA'],\n\t\t\tnbox:'nbox',\n\t\t\tpbox:'pbox',\n\t\t\tevent:'click',\n\t\t\tinterval:5,\n\t        onchange:function(_index){\n\t            // ok(true,'切换到'+_index+'页');\n\t            // start();\n\t        }\n\t\t});\n\t});\n    //开始单元测试\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}cycler.test.js',\n    ['{lib}util/cycler/cycler.js'],f);\n});\n"
  },
  {
    "path": "src/util/data/portrait/portrait.js",
    "content": "/*\n * ------------------------------------------\n * 表情数据缓存实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/data/portrait/portrait */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/config',\n    'base/element',\n    'base/util',\n    'util/cache/abstract'\n],function(NEJ,_k,_c,_e,_u,_t0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 表情数据缓存，缓存对象可直接用于nej.ut._$$ListModule\n     * \n     * 表情资源可通过以下git仓库直接下载到本地\n     * \n     * {@link https://github.com/genify/nej-portrait.git}\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/data/portrait/portrait'\n     * ],function(_t){\n     *     var _cache = _t._$$CachePortrait._$allocate({\n     *         onlistload:function(){\n     *             // TODO\n     *         }\n     *     });\n     *     \n     *     // 取表情分类列表\n     *     _cache._$getList({\n     *         key:'portrait-type',\n     *         offset:0,\n     *         limit:1000,\n     *         data:{\n     *             type:'type'\n     *         }\n     *     });\n     *     \n     *     // 取某类表情列表\n     *     _cache._$getList({\n     *         key:'portrait-face-0',\n     *         offset:0,\n     *         limit:1000,\n     *         data:{\n     *             type:'face'\n     *         }\n     *     });\n     * });\n     * ```\n     * \n     * @class   module:util/data/portrait/portrait._$$CachePortrait\n     * @extends module:util/cache/abstract._$$CacheListAbstract\n     * \n     * @param   {Object} config - 可选配置参数\n     */\n    _p._$$CachePortrait = _k._$klass();\n    _pro = _p._$$CachePortrait._$extend(_t0._$$CacheListAbstract);\n    /**\n     * 载入表情列表\n     * \n     * @protected\n     * @method   module:util/data/portrait/portrait._$$CachePortrait#__doLoadList\n     * @param    {Object}   config - 请求信息\n     * @property {String}   key    - 列表标识\n     * @property {Number}   offset - 偏移量\n     * @property {Number}   limit  - 数量\n     * @property {String}   data   - 请求相关数据\n     * @property {Function} onload - 列表载入回调\n     * @return   {Void}\n     */\n    _pro.__doLoadList = function(_options){\n        var _type = (_options.data||_o).type||'',\n            _list = _dmap[_type]||[],\n            _root = _c._$get('portrait');\n        if (!(_list[0]||_o).id){\n            _u._$forEach(\n                _list,function(_value,_index){\n                    _list[_index] = {\n                        text:_value,\n                        id:_type+'-'+_index,\n                        url:_root+_type+'/preview/'+_type+_index+'.gif'\n                    };\n                }\n            );\n        }else if(_type=='type'&&(_list[0]||_o).total==null){\n            _u._$forEach(\n                _list,function(_item){\n                    _item.total = (_dmap[_item.id]||_r).length;\n                }\n            );\n        }\n        _options.onload({\n            list:_list,\n            total:_list.length\n        });\n    };\n    // init data\n    var _dmap = {\n        type:[\n            {id:'face',name:'泡泡',size:30},\n            {id:'yayun',name:'亚运表情',size:60},\n            {id:'popo',name:'大泡泡',size:30},\n            {id:'west',name:'梦幻西游',size:30},\n            {id:'bear',name:'蛋壳熊',size:60},\n            {id:'tu',name:'兔儿控',size:60},\n            {id:'r',name:'土豆仔',size:60},\n            {id:'g',name:'绿头巾',size:60},\n            {id:'mayang',name:'玛央猫',size:60},\n            {id:'nai',name:'奶瓶仔',size:60},\n            {id:'minimo',name:'帽帽鼠',size:60},\n            {id:'mliho',name:'唛哩轰',size:60},\n            {id:'liki',name:'liki公主',size:60},\n            {id:'mx',name:'麦咪熊熊',size:60},\n            {id:'xiayu',name:'小夏',size:60},\n            {id:'cobo',name:'酷巴熊',size:60},\n            {id:'pop',name:'泡泡兵',size:60},\n            {id:'meaky',name:'怪物熊猫',size:60},\n            {id:'wuzhi',name:'无知熊猫',size:60},\n            {id:'peg',name:'PEG',size:60},\n            {id:'frogleon',name:'绿豆蛙',size:60},\n            {id:'zhuxiaoliang',name:'猪小梁',size:60},\n            {id:'popomm',name:'泡泡妹',size:60}\n        ],\n        face:['微笑','开怀笑','哭泣','失望','困了','好好笑','啵','电到了','汗','流口水了','真困啊','我吐','眨眼','？？？','嘘','砸死你','不说','坏','色迷迷','教训','可爱','YEAH','崩溃','惊讶','鄙视','开心','仰慕你','晕','挖鼻孔','撒娇','鼓掌','害羞','老大','欠揍','吐舌笑脸','飞吻','工作忙','大哭','偷偷笑','送花给你','来，亲一个','拍桌子','拜拜','得意的笑','生气','怕怕','尴尬','难过','叹气','我是女生','玫瑰','好爱你','心碎了','亲亲','NO','YES','握个手','到点了','音乐','我是男生','带血的刀','炸弹','有了','好晚了','吸血蝙蝠','便便','干一杯','抽烟','打电话','家','车子','礼物','金钱','太阳','下雨','猪猪','小猫','小狗','骨头','喝水','汉堡','包子','西瓜','约会','CALL我'],\n        yayun:['游泳','跳水','水球','花样游泳','射箭','田径','羽毛球','棒球','篮球','拳击','皮划艇静水','皮划艇激流回旋','自行车场地赛','自行车公路赛','自行车山地赛','自行车小轮车赛','马术','击剑','足球','体操','蹦床','艺术体操','手球','曲棍球','柔道','现代五项','赛艇','帆船','射击','射击飞碟','垒球','乒乓球','跆拳道','网球','软式网球','铁人三项','排球','沙滩排球','举重','摔跤','保龄球','台球','体育舞蹈','龙舟','高尔夫球','卡巴迪','空手道','轮滑','橄榄球','藤球','壁球','武术','国际象棋','围棋','中国象棋','板球','自由泳','仰泳','蛙泳','蝶泳','跳台','跳板','标枪','铅球','撑竿跳','跨栏','跳远','掷铁饼','链球','七项全能','十项全能','跳马','自由体操','单杠','双杠','高低杠','鞍马','吊环','平衡木','反对','支持','拉拉队','中国队加油'],\n        popo:['饶了我','敢惹我','蜘蛛侠','微笑','抓狂','流鼻血','谁放p','开饭了','崇拜','血窟窿','不是吧','打哈欠','真衰','大家好','投降','大笑','流口水','老大','雄霸','命歹啊','亲你','痛哭','挨揍','脸肿','服了','傲慢','得意','满意','汗','可怜','怒了','傻笑','伤心','倒霉','鬼脸','羡慕','偷看','绷带','挨砖','挨铁球','好色','行星','害羞','泪流','烧香','挨扁','不敢了','哈哈','强','寒','爽啊','惊讶','yoyo','太有才','吓我','出击','耍酷','缺牙','又打我','友好','黑心','我哭','骷髅','白牙','掉眼球','戴花','我也要','美味','狂笑','眯眼','晕死','爱财','发呆','滴汗','爱你','哼哼','眼镜','怕了','大小眼','飞天侠','甲虫脸','错愕','欢迎','不懂','标枪','风帆','击剑','跨栏MM','跨栏','马术','平衡木','铅球','拳击','射击','射箭','手球','跆拳道','田径','田径MM','跳马','铁饼','棒球','撑竿跳','弹床','吊环','举重','排球','皮划艇','皮划艇','乒乓','自行车','曲棍球','沙滩排球','水上排球','体操','跳台','网球','游泳','羽毛球','加油！'],\n        west:['微笑','开心','得意','晕了','怕了吧','蝙蝠','牛奶','小狗','心碎了','爱你','蛋糕','握手','时钟','咖啡','不爽','痛哭','牛头','脸红','阴险吧','再见','帅哥','亲一个','电话','献花','不是吧','吐舌头','yes','no','爽啊','小猪','灯泡','可乐','骂人','礼物','晚安','讨厌','乌云','yeah','你好','扇风','眯眼','飞吻','唱歌','臭美','庆祝','惊叹','叫好','安慰','我行啊','崩溃','胜利了','叫好','我哭','可爱','不爽','疑问','憨笑','call我','不错哦','休息','呸','欢呼','大笑','哈哈','飞行','呕吐','挨揍','我闭嘴','困了','晦气','就医','鄙视','喜欢你','回来了','汗','加油','厉害','高兴','倒霉','我顶','流口水','速度','不理你','欢迎','恭喜','邮件','瞧我的','爱意','色迷迷','亲爱的','不稀罕','强','喝酒','完蛋','蓬头','拜拜','爽啊','献花','快来人','念经','下雨了','快记','小看你','溜走'],\n        bear:['打球','我听话','吃零食','写字','跳舞','吹气','肚皮舞','无聊哦','吃饭了','吃冰棍','大笑','发火','击球','揍你','唱歌','眨眼睛','打喷嚏','纳闷','爆发吧','做鬼脸','威胁','玩彩球','星月','挨揍','哼歌','魔法棒','舞大刀','再见','扩胸'],\n        tu:['正义超人陈队','大八卦','啊~~~死掉了','吃饱饱','HAPPY~~','哇 哈哈哈','好急好急','好开心','BS你','星星眼','正义超人','调皮','WS老别别','钢琴小王子','挖啊挖鼻孔','爆炸芭蕾','风尘式抽烟','华丽转圈圈','色别别归来','拉拉队长','第一手','草莓星星眼','撒娇撒娇','弱弱小鸡','心永不变','我追呀追','我跑呀跑','梨花带雨','不要离开我','含蓄滴脸红','怨念','抓狂','WS偷偷笑','欢迎欢迎','热烈欢迎','坏坏扭扭','色色扭扭','忠心扭扭','勾人的小妞','帅锅','WS眼镜男','华丽吐啊吐','指着鼻子骂','伤心滴飘走','不倒翁','喝醉鸟','不爽','121 121 121','软绵绵滴撒娇','摇啊摇','激烈滴撒娇','小白扭扭','小黑扭扭','怕不怕啊','小白跳舞','小黑跳舞','小白跳舞','小黑跳舞','HAPPY小暴牙','钢琴小公主','钢琴小王子','美少女花子','垂涎美色滴WSN~~~~','是说我吗','在做什么捏','僵尸宝宝','僵尸妈妈','僵尸爸爸','僵尸爷爷','一起跳~~','一起跳~~','天生一对','白扭扭队','黑扭扭队','僵尸家族出游鸟~~~','偶棉在浇花啊','啦啦啦~','心花怒放','大心~~','蹲地发呆','招手','喔~~~','扇扇风左','少奶奶打招呼','扇扇风右','圣诞快乐','圣诞树','洗白白',' 绿茶面膜','巧克力面膜','睡得香','臭屁轰炸','生气厨娘','快乐游泳','比基尼','恭喜发财','招财进宝','吉祥如意','对不起','不想起床','抱抱','蹬腿','兔子火锅','情人节快乐','胡思乱想','小可爱','小三八','抓抓手','生日快乐','顿脚','摇摇椅','贱贱扭扭腰','乖乖扭扭腰','蓝蓝路','奥运火炬手','鼠宝宝','牛宝宝','虎宝宝','兔宝宝','龙宝宝','蛇宝宝','马宝宝','羊宝宝','猴宝宝','鸡宝宝','狗宝宝','猪宝宝','棒棒糖','吃冰棒','划水','玩水','假假PMP','忠心PMP'],\n        r:['慢慢来嘛','可恶啊','扭扭捏捏','阴险','我就说啊','弹吉他','唱歌','你给我记着','好笑','太好笑了','怎么!?','听我的','换脑壳','不会吧!','摇摆','扭动','瀑布汗','我吐','呼啦圈','怎么这样...','呜呜','真的吗!!','好心痛!','这个这个这个','Yin笑','喵呜','你就吹吧!','咳嗽','你啊你啊!','潜水','气绝','小声点!','NONONO','怎么办怎么办?','削皮','我是LOLI','鼓掌','扭头','这边不对那边不对!','喷饭!','拜拜','冲啊','亲亲','有弹性就有魅力','好冷','摇摇晃晃','捏你','失落','你就扯吧!','有惊喜!','啊呀呀呀!','翻滚中','滚圈圈','鄙视你!','打喷嚏','来呀来呀!~','头很光滑','我说没说过!','华丽摇摆!','就是这样','晕厥～','啊？？','单挑！','我刷啊刷压','我洗啊洗脸','长角...','僵尸','我变我变变','我切我切切','秀逗了？','做鬼脸','杀人狂魔','我舔～～','撞墙啦','冲啊～','打冷战','点头','滚来滚去','雀跃啊','休息了','撞头党'],\n        g:['羞羞','叹气','爱哟~','锻炼','扯虾米','88','好重','欺负人','不活了','讨厌啦','好HIGH','燃了！','亲爱D','喝茶','头晕','很有才','驾~','亢奋','惊！','吓！','摸头','不要吖~','抖~','脸色铁青','红牌','NONO','抬眼镜','天使','亲亲','打拳','这样吗','叹','恶魔','超亢奋','哪里哪里','受打击','喝酒','啊哦','受刺激！','学习','怕怕','尿急','花痴','受伤','抠鼻子','超人','好爱吖','欺负人','飘~','切~','摇吖摇','钓鱼','郁闷'],\n        mayang:['戳苍蝇','忽悠','偷窥','飞','鬼脸','刷牙','隐身','吃汉堡','我们是冠军','熏苍蝇','被球砸','摇头','转头斜视','吹风','尿尿','叹气','临危不乱','惊讶','打劫','鬼','汗','喷火','飘过','亲','顶','狡猾','怒','中指','睡觉','问号','大惊','生气','胜利','耶','坐禅','哭','大笑','喊号','比手势'],\n        nai:['被揍','猫猫','我爱奶瓶','爱心','祈祷','再见','不耐烦','下流手势','看着奶瓶狂笑','伤心咬奶瓶','怒火','狂笑','微笑','烦恼','凌厉的眼光','拜奶瓶','懒虫喝奶','抱着奶瓶睡觉','趴在地上哭','自虐','疑问','皱眉头','路过','吐舌头','号啕大哭','大吐舌头','害羞','亲亲奶瓶','胜利手势','犯困','指挥','幽灵','生气想揍人'],\n        minimo:['好喜欢','棒','你好','飘过','鼓掌','不明白','晕','新年好','汗','哭','可爱','我是女王','我吐','玩耍','加油','吃东西','恭贺新春','钱啊钱','好冷','有计谋','嘲笑','潜水太久','不会吧','不要','睡觉','扭扭捏捏','发财拉','不行','哈哈','路过','怕怕','献吻','涮牙了','好气','我错了','再见','鬼','藐视','电你','尴尬','偷看','胜利','郁闷','找打','惊'],\n        mliho:['吃东西','你欺负我','嘿嘿','欢迎','亲爱的','发火','偷亲','笑死了','吐血','再见','快亲我','很好很强大','耍赖','我吐','我汗','爆发','数钱','逗你玩','恭喜','着迷','听话','喜欢','疼爱','恶整','起床啦','伤心','鬼脸','不会吧','疑惑','有美女吖','刷牙啦','超人','我来啦','看不见','发怒','别惹我','噪音攻击','报复','反攻击','坏笑','满足','害羞','欢呼','落魄','无视','探勘','求饶','吸引','虐待','很乖'],\n        liki:['ok','偷笑','大笑','害羞','腼典','撒娇','崇拜','仰慕','怒骂','失望','大惊','向前进','老大','教训','哭','大哭','委屈','献花','晕','撒皮','乖','加油','寒','见鬼','刷牙','超人'],\n        mx:['拍手','抚摸','汗','诡笑','眨眼','棒棒糖','豆眼','点头','摇头','蹭','来抱抱','乃人噢','开心跳','happy','看热闹','生日快乐','亲亲','氺汪汪','好冷','看','一起来','得意','扭呀扭','拨耳朵','美滋滋','可怕','亲宝贝','揉揉','工作','不高兴','啦啦','偷笑','奇怪','吃','惊','私语','抽咽','委屈','流泪','哭','强吻','偷看','抱住','献花','跳舞','hi','睡','冷哇','么么','困','亲','不要','无语','魂','再见','我说','大步走','摆手','扭动','噢噢噢'],\n        xiayu:['555哭','凉快','介个','无语','哼哼~~','happy~','我来啦','耶~','我扑','委屈','love','困了','前进','思考','肚子痛','love','困了','前进','思考','肚子痛','吃饭中','睡觉觉','化妆','变脸','什么','打针','忙','可怜的哭','坏笑','不耐烦','喝果汁','疯','怒视','很强大','傻呆呆','好主意','no','甩葱','脸红'],\n        cobo:['不活啦','瞌睡','嘻！嘻！','斗虫虫','NO!NO!','Hi!','琢磨！琢磨！','撞墙','嘘！','嘻！嘻！','潜水中','偷笑','亲亲','再变','笑崩溃','我变','嘿哈','敬礼','推','好HAPPY哦','变','嘿嘿','来呀','陶醉','逗你','扭扭','翻过','得意','我飘','旋转快乐','左右扭','新年快乐','滚来滚去','放炮啦','恭喜发财','耶～','加油～','感冒了','别理我','吐舌头','我跳','看我的','北京欢迎你','看箭','中国加油','我顶','我跳','揍你','力气太大了吗','我劈','啷哩个啷','鲤鱼跳','熊式游法','我顶','汗。。。','我画圈圈','顶！！','同志们好～','被雷到','脑残','我戳我戳','已阅','得意','耶！','啊～～','臭屁','这里这里...','不会吧...','哦？','哼！','我来啦～','听音乐','看招！','哦','得得意意','啊 切','看招！','草裙舞','啦啦啦','啦啦啦','泪眼花花','看招！','啊～哈！','我！老大！','熊家拳！','嘘！小声点!','旋转快乐！','晕','琢磨','撞墙','找抽','豆豆','嘿哈','黄飞熊','降龙十八掌','觉觉','啊～切～～','美女','88','笑死我了','让我们集结吧！','装可爱','我来啦～','88','泪啊～','no no'],\n        pop:['吃饭','晕','抓狂','喷血','哭','抽你','吐了','扫射','潜水','BIBI','KAO','抽烟','捏你','抱抱','汗','爽啊','我甩','舔你','哟西','去你的','我吐','回来','看你狂不','感动','喷水','你好棒','你……我倒','早','洗澡澡',' “鹿”过','开枪','蝙蝠侠','我“滚”呀“滚”','找我啥事','恰我一拳','抠鼻鼻','好困那','哼','拜托拉','好寒那','爆头','发飚啦','大笑',' 痴笑','大寒'],\n        meaky:['抽烟','鄙视','媒婆','大笑','困了','浪舞','凄凉','大哭','倒了','很馋','嘁~','膜拜','怒奔','自残'],\n        wuzhi:['火炬接力','石化','元气满点','俯卧撑','发呆','恐怖','蓝蓝路','不好意思','生日快乐','懒','无所谓','生病','星星眼','谢谢','偷窥','kiss','打飞','皮又痒了','鄙视你','砍死你','眼泪汪汪','挖鼻子','大笑','暴走','sm','orz','晕','色眯眯','咬住','不良','华丽登场','捏脸','吃面包','摇头晃脑','瞌睡','挠挠','怒','思考'],\n        peg:['困啦','嘿嘿...','喵～','气死我了','我爱漂漂','刷牙','真好吃','好呀','伤心','搅啊搅拌','我晕','寒～','吃瓜瓜','我爱大包','吸面功'],\n        frogleon:['开心','伤心','惊恐','怒','疑惑','可爱','白眼','伤心','委屈','喜悦','痛苦','狂喜','庆祝','惊讶','贼笑','雀跃','咬牙切齿','不爽','胆小怕事','被扁','冷汗','可怜','吃惊','抓狂','无奈','惊喜','害怕','忐忑','发疯','感动'],\n        zhuxiaoliang:['我飞～','跑路喽','快跑','跳舞','扮花花','扮苍蝇','中箭','哭给你看','电死你','出发','吃饭啦','好吃','飘过','泡咖啡','泡茶'],\n        popomm:['同意','怕怕','女侠','高兴','做面膜','杂耍','病了','困了','咳咳','生气','不要啊 ','撅嘴','嗯嗯','请安','为什么','怒','爱心','可爱']\n    };\n\n    if (CMPT){\n        NEJ.P('nej.ut')._$$PortraitCache = _p._$$CachePortrait;\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/data/region/zh.js",
    "content": "/*\n * ------------------------------------------\n * 中国行政划区数据缓存实现文件\n * 数据来源：http://www.stats.gov.cn/tjbz/xzqhdm/t20120105_402777427.htm\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/data/region/zh */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/cache/abstract'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 中国行政划区数据缓存\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/data/region/zh'\n     * ],function(_t){\n     *     var _cache = _t._$$CacheRegionZH._$allocate();\n     *     \n     *     // 取省份列表\n     *     _cache._$getList({key:'province'});\n     *     // 取某个省份的城市列表\n     *     // key为'city-'+省份名称\n     *     _cache._$getList({key:'city-浙江省'});\n     *     // 取某个省份城市下的区域列表\n     *     // key为'area-'+省份名称+'-'+城市名称\n     *     _cache._$getList({key:'area-浙江省-杭州市'});\n     * });\n     * ```\n     * \n     * @class   module:util/data/region/zh._$$CacheRegionZH\n     * @extends module:util/cache/abstract._$$CacheListAbstract\n     * \n     * @param   {Object} config 可选配置参数\n     */\n    _p._$$CacheRegionZH = _k._$klass();\n    _pro = _p._$$CacheRegionZH._$extend(_t0._$$CacheListAbstract);\n    /**\n     * 从服务器端载入列表\n     * \n     * @protected\n     * @method   module:util/data/region/zh._$$CacheRegionZH#__doLoadList\n     * @param    {Object}   arg0   - 请求信息\n     * @property {String}   key    - 列表标识\n     * @property {Number}   offset - 偏移量\n     * @property {Number}   limit  - 数量\n     * @property {String}   data   - 请求相关数据\n     * @property {Function} onload - 列表载入回调\n     * @return   {Void}\n     */\n    _pro.__doLoadList = function(_options){\n        var _list,\n            _arr = _options.key.split('-');\n        switch(_arr.shift()){\n            case 'province':\n                _list = this.__getProvinceList();\n            break;\n            case 'city':\n                _list = this.__getCityList(_arr[0]);\n            break;\n            case 'area':\n                _list = this.__getAreaList(_arr[0],_arr[1]);\n            break;\n        }\n        // callback\n        _options.onload({\n            list:_list,\n            total:_list.length\n        });\n    };\n    /**\n     * 取省份列表\n     * @protected\n     *\n     * @method   module:util/data/region/zh._$$CacheRegionZH#__getProvinceList\n     * @return {Array} 省份列表\n     */\n    _pro.__getProvinceList = function(){\n         return _dmap.p||[];\n    };\n    /**\n     * 取城市列表\n     * @protected\n     *\n     * @method   module:util/data/region/zh._$$CacheRegionZH#__getCityList\n     * @param  {String} arg0 - 省名称\n     * @return {Array}  城市列表\n     */\n    _pro.__getCityList = function(_province){\n        return _dmap.c[_province]||[];\n    };\n    /**\n     * 取区域列表\n     * @protected\n     *\n     * @method   module:util/data/region/zh._$$CacheRegionZH#__getAreaList\n     * @param  {String} arg0 - 省名称\n     * @return {Array}  城市列表\n     */\n    _pro.__getAreaList = function(_province,_city){\n        return _dmap.a[_province+'-'+_city]||[];\n    };\n    /**\n     * 判断给定省份是否有三级目录\n     * \n     * @method module:util/data/region/zh._$$CacheRegionZH#_$hasArea\n     * @param  {String}  arg0 - 省份\n     * @return {Boolean}        是否有三级目录\n     */\n    _pro._$hasArea = function(_province){\n        return !_dmap.s[_province];\n    };\n    // init data\n    var _dmap = {\n         s:{'北京市':1,'天津市':1,'上海市':1,'重庆市':1,'澳门特别行政区':1,'香港特别行政区':1},\n         p:['北京市','天津市','上海市','重庆市','河北省','山西省','辽宁省','吉林省','黑龙江省','江苏省','浙江省','安徽省','福建省','江西省','山东省','河南省','湖北省','湖南省','广东省','海南省','四川省','贵州省','云南省','陕西省','甘肃省','青海省','西藏自治区','内蒙古自治区','广西壮族自治区','宁夏回族自治区','新疆维吾尔自治区','香港特别行政区','澳门特别行政区','台湾省'],\n         c:{'北京市':['东城区','西城区','朝阳区','丰台区','石景山区','海淀区','门头沟区','房山区','通州区','顺义区','昌平区','大兴区','怀柔区','平谷区','密云县','延庆县'],\n            '天津市':['和平区','河东区','河西区','南开区','河北区','红桥区','东丽区','西青区','津南区','北辰区','武清区','宝坻区','滨海新区','宁河县','静海县','蓟县'],\n            '河北省':['石家庄市','唐山市','秦皇岛市','邯郸市','邢台市','保定市','张家口市','承德市','沧州市','廊坊市','衡水市'],\n            '山西省':['太原市','大同市','阳泉市','长治市','晋城市','朔州市','晋中市','运城市','忻州市','临汾市','吕梁市'],\n            '内蒙古自治区':['呼和浩特市','包头市','乌海市','赤峰市','通辽市','鄂尔多斯市','呼伦贝尔市','巴彦淖尔市','乌兰察布市','兴安盟','锡林郭勒盟','阿拉善盟'],\n            '辽宁省':['沈阳市','大连市','鞍山市','抚顺市','本溪市','丹东市','锦州市','营口市','阜新市','辽阳市','盘锦市','铁岭市','朝阳市','葫芦岛市'],\n            '吉林省':['长春市','吉林市','四平市','辽源市','通化市','白山市','松原市','白城市','延边朝鲜族自治州'],\n            '黑龙江省':['哈尔滨市','齐齐哈尔市','鸡西市','鹤岗市','双鸭山市','大庆市','伊春市','佳木斯市','七台河市','牡丹江市','黑河市','绥化市','大兴安岭地区'],\n            '上海市':['黄浦区','徐汇区','长宁区','静安区','普陀区','闸北区','虹口区','杨浦区','闵行区','宝山区','嘉定区','浦东新区','金山区','松江区','青浦区','奉贤区','崇明县'],\n            '江苏省':['南京市','无锡市','徐州市','常州市','苏州市','南通市','连云港市','淮安市','盐城市','扬州市','镇江市','泰州市','宿迁市'],\n            '浙江省':['杭州市','宁波市','温州市','嘉兴市','湖州市','绍兴市','金华市','衢州市','舟山市','台州市','丽水市'],\n            '安徽省':['合肥市','芜湖市','蚌埠市','淮南市','马鞍山市','淮北市','铜陵市','安庆市','黄山市','滁州市','阜阳市','宿州市','六安市','亳州市','池州市','宣城市'],\n            '福建省':['福州市','厦门市','莆田市','三明市','泉州市','漳州市','南平市','龙岩市','宁德市'],\n            '江西省':['南昌市','景德镇市','萍乡市','九江市','新余市','鹰潭市','赣州市','吉安市','宜春市','抚州市','上饶市'],\n            '山东省':['济南市','青岛市','淄博市','枣庄市','东营市','烟台市','潍坊市','济宁市','泰安市','威海市','日照市','莱芜市','临沂市','德州市','聊城市','滨州市','菏泽市'],\n            '河南省':['郑州市','开封市','洛阳市','平顶山市','安阳市','鹤壁市','新乡市','焦作市','濮阳市','许昌市','漯河市','三门峡市','南阳市','商丘市','信阳市','周口市','驻马店市','省直辖县级行政区划'],\n            '湖北省':['武汉市','黄石市','十堰市','宜昌市','襄阳市','鄂州市','荆门市','孝感市','荆州市','黄冈市','咸宁市','随州市','恩施土家族苗族自治州','省直辖县级行政区划'],\n            '湖南省':['长沙市','株洲市','湘潭市','衡阳市','邵阳市','岳阳市','常德市','张家界市','益阳市','郴州市','永州市','怀化市','娄底市','湘西土家族苗族自治州'],\n            '广东省':['广州市','韶关市','深圳市','珠海市','汕头市','佛山市','江门市','湛江市','茂名市','肇庆市','惠州市','梅州市','汕尾市','河源市','阳江市','清远市','东莞市','中山市','潮州市','揭阳市','云浮市'],\n            '广西壮族自治区':['南宁市','柳州市','桂林市','梧州市','北海市','防城港市','钦州市','贵港市','玉林市','百色市','贺州市','河池市','来宾市','崇左市'],\n            '海南省':['海口市','三亚市','三沙市','省直辖县级行政区划'],\n            '重庆市':['万州区','涪陵区','渝中区','大渡口区','江北区','沙坪坝区','九龙坡区','南岸区','北碚区','綦江区','大足区','渝北区','巴南区','黔江区','长寿区','江津区','合川区','永川区','南川区','潼南县','铜梁县','荣昌县','璧山县','梁平县','城口县','丰都县','垫江县','武隆县','忠县','开县','云阳县','奉节县','巫山县','巫溪县','石柱土家族自治县','秀山土家族苗族自治县','酉阳土家族苗族自治县','彭水苗族土家族自治县'],\n            '四川省':['成都市','自贡市','攀枝花市','泸州市','德阳市','绵阳市','广元市','遂宁市','内江市','乐山市','南充市','眉山市','宜宾市','广安市','达州市','雅安市','巴中市','资阳市','阿坝藏族羌族自治州','甘孜藏族自治州','凉山彝族自治州'],\n            '贵州省':['贵阳市','六盘水市','遵义市','安顺市','毕节市','铜仁市','黔西南布依族苗族自治州','黔东南苗族侗族自治州','黔南布依族苗族自治州'],\n            '云南省':['昆明市','曲靖市','玉溪市','保山市','昭通市','丽江市','普洱市','临沧市','楚雄彝族自治州','红河哈尼族彝族自治州','文山壮族苗族自治州','西双版纳傣族自治州','大理白族自治州','德宏傣族景颇族自治州','怒江傈僳族自治州','迪庆藏族自治州'],\n            '西藏自治区':['拉萨市','昌都地区','山南地区','日喀则地区','那曲地区','阿里地区','林芝地区'],\n            '陕西省':['西安市','铜川市','宝鸡市','咸阳市','渭南市','延安市','汉中市','榆林市','安康市','商洛市'],\n            '甘肃省':['兰州市','嘉峪关市','金昌市','白银市','天水市','武威市','张掖市','平凉市','酒泉市','庆阳市','定西市','陇南市','临夏回族自治州','甘南藏族自治州'],\n            '青海省':['西宁市','海东地区','海北藏族自治州','黄南藏族自治州','海南藏族自治州','果洛藏族自治州','玉树藏族自治州','海西蒙古族藏族自治州'],\n            '宁夏回族自治区':['银川市','石嘴山市','吴忠市','固原市','中卫市'],\n            '新疆维吾尔自治区':['乌鲁木齐市','克拉玛依市','吐鲁番地区','哈密地区','昌吉回族自治州','博尔塔拉蒙古自治州','巴音郭楞蒙古自治州','阿克苏地区','克孜勒苏柯尔克孜自治州','喀什地区','和田地区','伊犁哈萨克自治州','塔城地区','阿勒泰地区','自治区直辖县级行政区划'],\n            '香港特别行政区':['中西区','东区','南区','湾仔区','九龙城区','深水埗区','油尖旺区','黄大仙区','观塘区','离岛区','葵青区','荃湾区','屯门区','元朗区','北区','大埔区','西贡区','沙田区'],\n            '澳门特别行政区':['花地玛堂区','圣安多尼堂区','大堂区','望德堂区','风顺堂区','嘉模堂区','圣方济各堂区','路氹城'],\n            '台湾省':['台北市','台中市','台南市','高雄市','新北市','新竹市','嘉义市','基隆市','云林县','南投县','台东县','嘉义县','宜兰县','屏东县','彰化县','新竹县','桃园县','澎湖县','花莲县','苗栗县','连江县','金门县']\n         },\n         a:{'河北省-石家庄市':['长安区','桥东区','桥西区','新华区','井陉矿区','裕华区','井陉县','正定县','栾城县','行唐县','灵寿县','高邑县','深泽县','赞皇县','无极县','平山县','元氏县','赵县','辛集市','藁城市','晋州市','新乐市','鹿泉市'],\n            '河北省-唐山市':['路南区','路北区','古冶区','开平区','丰南区','丰润区','滦县','滦南县','乐亭县','迁西县','玉田县','唐海县','遵化市','迁安市'],\n            '河北省-秦皇岛市':['海港区','山海关区','北戴河区','青龙满族自治县','昌黎县','抚宁县','卢龙县'],\n            '河北省-邯郸市':['邯山区','丛台区','复兴区','峰峰矿区','邯郸县','临漳县','成安县','大名县','涉县','磁县','肥乡县','永年县','邱县','鸡泽县','广平县','馆陶县','魏县','曲周县','武安市'],\n            '河北省-邢台市':['桥东区','桥西区','邢台县','临城县','内丘县','柏乡县','隆尧县','任县','南和县','宁晋县','巨鹿县','新河县','广宗县','平乡县','威县','清河县','临西县','南宫市','沙河市'],\n            '河北省-保定市':['新市区','北市区','南市区','满城县','清苑县','涞水县','阜平县','徐水县','定兴县','唐县','高阳县','容城县','涞源县','望都县','安新县','易县','曲阳县','蠡县','顺平县','博野县','雄县','涿州市','定州市','安国市','高碑店市'],\n            '河北省-张家口市':['桥东区','桥西区','宣化区','下花园区','宣化县','张北县','康保县','沽源县','尚义县','蔚县','阳原县','怀安县','万全县','怀来县','涿鹿县','赤城县','崇礼县'],\n            '河北省-承德市':['双桥区','双滦区','鹰手营子矿区','承德县','兴隆县','平泉县','滦平县','隆化县','丰宁满族自治县','宽城满族自治县','围场满族蒙古族自治县'],\n            '河北省-沧州市':['新华区','运河区','沧县','青县','东光县','海兴县','盐山县','肃宁县','南皮县','吴桥县','献县','孟村回族自治县','泊头市','任丘市','黄骅市','河间市'],\n            '河北省-廊坊市':['安次区','广阳区','固安县','永清县','香河县','大城县','文安县','大厂回族自治县','霸州市','三河市'],\n            '河北省-衡水市':['桃城区','枣强县','武邑县','武强县','饶阳县','安平县','故城县','景县','阜城县','冀州市','深州市'],\n            '山西省-太原市':['小店区','迎泽区','杏花岭区','尖草坪区','万柏林区','晋源区','清徐县','阳曲县','娄烦县','古交市'],\n            '山西省-大同市':['城区','矿区','南郊区','新荣区','阳高县','天镇县','广灵县','灵丘县','浑源县','左云县','大同县'],\n            '山西省-阳泉市':['城区','矿区','郊区','平定县','盂县'],\n            '山西省-长治市':['城区','郊区','长治县','襄垣县','屯留县','平顺县','黎城县','壶关县','长子县','武乡县','沁县','沁源县','潞城市'],\n            '山西省-晋城市':['城区','沁水县','阳城县','陵川县','泽州县','高平市'],\n            '山西省-朔州市':['朔城区','平鲁区','山阴县','应县','右玉县','怀仁县'],\n            '山西省-晋中市':['榆次区','榆社县','左权县','和顺县','昔阳县','寿阳县','太谷县','祁县','平遥县','灵石县','介休市'],\n            '山西省-运城市':['盐湖区','临猗县','万荣县','闻喜县','稷山县','新绛县','绛县','垣曲县','夏县','平陆县','芮城县','永济市','河津市'],\n            '山西省-忻州市':['忻府区','定襄县','五台县','代县','繁峙县','宁武县','静乐县','神池县','五寨县','岢岚县','河曲县','保德县','偏关县','原平市'],\n            '山西省-临汾市':['尧都区','曲沃县','翼城县','襄汾县','洪洞县','古县','安泽县','浮山县','吉县','乡宁县','大宁县','隰县','永和县','蒲县','汾西县','侯马市','霍州市'],\n            '山西省-吕梁市':['离石区','文水县','交城县','兴县','临县','柳林县','石楼县','岚县','方山县','中阳县','交口县','孝义市','汾阳市'],\n            '内蒙古自治区-呼和浩特市':['新城区','回民区','玉泉区','赛罕区','土默特左旗','托克托县','和林格尔县','清水河县','武川县'],\n            '内蒙古自治区-包头市':['东河区','昆都仑区','青山区','石拐区','白云鄂博矿区','九原区','土默特右旗','固阳县','达尔罕茂明安联合旗'],\n            '内蒙古自治区-乌海市':['海勃湾区','海南区','乌达区'],\n            '内蒙古自治区-赤峰市':['红山区','元宝山区','松山区','阿鲁科尔沁旗','巴林左旗','巴林右旗','林西县','克什克腾旗','翁牛特旗','喀喇沁旗','宁城县','敖汉旗'],\n            '内蒙古自治区-通辽市':['科尔沁区','科尔沁左翼中旗','科尔沁左翼后旗','开鲁县','库伦旗','奈曼旗','扎鲁特旗','霍林郭勒市'],\n            '内蒙古自治区-鄂尔多斯市':['东胜区','达拉特旗','准格尔旗','鄂托克前旗','鄂托克旗','杭锦旗','乌审旗','伊金霍洛旗'],\n            '内蒙古自治区-呼伦贝尔市':['海拉尔区','阿荣旗','莫力达瓦达斡尔族自治旗','鄂伦春自治旗','鄂温克族自治旗','陈巴尔虎旗','新巴尔虎左旗','新巴尔虎右旗','满洲里市','牙克石市','扎兰屯市','额尔古纳市','根河市'],\n            '内蒙古自治区-巴彦淖尔市':['临河区','五原县','磴口县','乌拉特前旗','乌拉特中旗','乌拉特后旗','杭锦后旗'],\n            '内蒙古自治区-乌兰察布市':['集宁区','卓资县','化德县','商都县','兴和县','凉城县','察哈尔右翼前旗','察哈尔右翼中旗','察哈尔右翼后旗','四子王旗','丰镇市'],\n            '内蒙古自治区-兴安盟':['乌兰浩特市','阿尔山市','科尔沁右翼前旗','科尔沁右翼中旗','扎赉特旗','突泉县'],\n            '内蒙古自治区-锡林郭勒盟':['二连浩特市','锡林浩特市','阿巴嘎旗','苏尼特左旗','苏尼特右旗','东乌珠穆沁旗','西乌珠穆沁旗','太仆寺旗','镶黄旗','正镶白旗','正蓝旗','多伦县'],\n            '内蒙古自治区-阿拉善盟':['阿拉善左旗','阿拉善右旗','额济纳旗'],\n            '辽宁省-沈阳市':['和平区','沈河区','大东区','皇姑区','铁西区','苏家屯区','东陵区','沈北新区','于洪区','辽中县','康平县','法库县','新民市'],\n            '辽宁省-大连市':['中山区','西岗区','沙河口区','甘井子区','旅顺口区','金州区','长海县','瓦房店市','普兰店市','庄河市'],\n            '辽宁省-鞍山市':['铁东区','铁西区','立山区','千山区','台安县','岫岩满族自治县','海城市'],\n            '辽宁省-抚顺市':['新抚区','东洲区','望花区','顺城区','抚顺县','新宾满族自治县','清原满族自治县'],\n            '辽宁省-本溪市':['平山区','溪湖区','明山区','南芬区','本溪满族自治县','桓仁满族自治县'],\n            '辽宁省-丹东市':['元宝区','振兴区','振安区','宽甸满族自治县','东港市','凤城市'],\n            '辽宁省-锦州市':['古塔区','凌河区','太和区','黑山县','义县','凌海市','北镇市'],\n            '辽宁省-营口市':['站前区','西市区','鲅鱼圈区','老边区','盖州市','大石桥市'],\n            '辽宁省-阜新市':['海州区','新邱区','太平区','清河门区','细河区','阜新蒙古族自治县','彰武县'],\n            '辽宁省-辽阳市':['白塔区','文圣区','宏伟区','弓长岭区','太子河区','辽阳县','灯塔市'],\n            '辽宁省-盘锦市':['双台子区','兴隆台区','大洼县','盘山县'],\n            '辽宁省-铁岭市':['银州区','清河区','铁岭县','西丰县','昌图县','调兵山市','开原市'],\n            '辽宁省-朝阳市':['双塔区','龙城区','朝阳县','建平县','喀喇沁左翼蒙古族自治县','北票市','凌源市'],\n            '辽宁省-葫芦岛市':['连山区','龙港区','南票区','绥中县','建昌县','兴城市'],\n            '吉林省-长春市':['南关区','宽城区','朝阳区','二道区','绿园区','双阳区','农安县','九台市','榆树市','德惠市'],\n            '吉林省-吉林市':['昌邑区','龙潭区','船营区','丰满区','永吉县','蛟河市','桦甸市','舒兰市','磐石市'],\n            '吉林省-四平市':['铁西区','铁东区','梨树县','伊通满族自治县','公主岭市','双辽市'],\n            '吉林省-辽源市':['龙山区','西安区','东丰县','东辽县'],\n            '吉林省-通化市':['东昌区','二道江区','通化县','辉南县','柳河县','梅河口市','集安市'],\n            '吉林省-白山市':['八道江区','江源区','抚松县','靖宇县','长白朝鲜族自治县','临江市'],\n            '吉林省-松原市':['宁江区','前郭尔罗斯蒙古族自治县','长岭县','乾安县','扶余县'],\n            '吉林省-白城市':['洮北区','镇赉县','通榆县','洮南市','大安市'],\n            '吉林省-延边朝鲜族自治州':['延吉市','图们市','敦化市','珲春市','龙井市','和龙市','汪清县','安图县'],\n            '黑龙江省-哈尔滨市':['道里区','南岗区','道外区','平房区','松北区','香坊区','呼兰区','阿城区','依兰县','方正县','宾县','巴彦县','木兰县','通河县','延寿县','双城市','尚志市','五常市'],\n            '黑龙江省-齐齐哈尔市':['龙沙区','建华区','铁锋区','昂昂溪区','富拉尔基区','碾子山区','梅里斯达斡尔族区','龙江县','依安县','泰来县','甘南县','富裕县','克山县','克东县','拜泉县','讷河市'],\n            '黑龙江省-鸡西市':['鸡冠区','恒山区','滴道区','梨树区','城子河区','麻山区','鸡东县','虎林市','密山市'],\n            '黑龙江省-鹤岗市':['向阳区','工农区','南山区','兴安区','东山区','兴山区','萝北县','绥滨县'],\n            '黑龙江省-双鸭山市':['尖山区','岭东区','四方台区','宝山区','集贤县','友谊县','宝清县','饶河县'],\n            '黑龙江省-大庆市':['萨尔图区','龙凤区','让胡路区','红岗区','大同区','肇州县','肇源县','林甸县','杜尔伯特蒙古族自治县'],\n            '黑龙江省-伊春市':['伊春区','南岔区','友好区','西林区','翠峦区','新青区','美溪区','金山屯区','五营区','乌马河区','汤旺河区','带岭区','乌伊岭区','红星区','上甘岭区','嘉荫县','铁力市'],\n            '黑龙江省-佳木斯市':['向阳区','前进区','东风区','郊区','桦南县','桦川县','汤原县','抚远县','同江市','富锦市'],\n            '黑龙江省-七台河市':['新兴区','桃山区','茄子河区','勃利县'],\n            '黑龙江省-牡丹江市':['东安区','阳明区','爱民区','西安区','东宁县','林口县','绥芬河市','海林市','宁安市','穆棱市'],\n            '黑龙江省-黑河市':['爱辉区','嫩江县','逊克县','孙吴县','北安市','五大连池市'],\n            '黑龙江省-绥化市':['北林区','望奎县','兰西县','青冈县','庆安县','明水县','绥棱县','安达市','肇东市','海伦市'],\n            '黑龙江省-大兴安岭地区':['呼玛县','塔河县','漠河县'],\n            '江苏省-南京市':['玄武区','白下区','秦淮区','建邺区','鼓楼区','下关区','浦口区','栖霞区','雨花台区','江宁区','六合区','溧水县','高淳县'],\n            '江苏省-无锡市':['崇安区','南长区','北塘区','锡山区','惠山区','滨湖区','江阴市','宜兴市'],\n            '江苏省-徐州市':['鼓楼区','云龙区','贾汪区','泉山区','铜山区','丰县','沛县','睢宁县','新沂市','邳州市'],\n            '江苏省-常州市':['天宁区','钟楼区','戚墅堰区','新北区','武进区','溧阳市','金坛市'],\n            '江苏省-苏州市':['沧浪区','平江区','金阊区','虎丘区','吴中区','相城区','常熟市','张家港市','昆山市','吴江市','太仓市'],\n            '江苏省-南通市':['崇川区','港闸区','通州区','海安县','如东县','启东市','如皋市','海门市'],\n            '江苏省-连云港市':['连云区','新浦区','海州区','赣榆县','东海县','灌云县','灌南县'],\n            '江苏省-淮安市':['清河区','楚州区','淮阴区','清浦区','涟水县','洪泽县','盱眙县','金湖县'],\n            '江苏省-盐城市':['亭湖区','盐都区','响水县','滨海县','阜宁县','射阳县','建湖县','东台市','大丰市'],\n            '江苏省-扬州市':['广陵区','邗江区','江都区','宝应县','仪征市','高邮市'],\n            '江苏省-镇江市':['京口区','润州区','丹徒区','丹阳市','扬中市','句容市'],\n            '江苏省-泰州市':['海陵区','高港区','兴化市','靖江市','泰兴市','姜堰市'],\n            '江苏省-宿迁市':['宿城区','宿豫区','沭阳县','泗阳县','泗洪县'],\n            '浙江省-杭州市':['上城区','下城区','江干区','拱墅区','西湖区','滨江区','萧山区','余杭区','桐庐县','淳安县','建德市','富阳市','临安市'],\n            '浙江省-宁波市':['海曙区','江东区','江北区','北仑区','镇海区','鄞州区','象山县','宁海县','余姚市','慈溪市','奉化市'],\n            '浙江省-温州市':['鹿城区','龙湾区','瓯海区','洞头县','永嘉县','平阳县','苍南县','文成县','泰顺县','瑞安市','乐清市'],\n            '浙江省-嘉兴市':['南湖区','秀洲区','嘉善县','海盐县','海宁市','平湖市','桐乡市'],\n            '浙江省-湖州市':['吴兴区','南浔区','德清县','长兴县','安吉县'],\n            '浙江省-绍兴市':['越城区','绍兴县','新昌县','诸暨市','上虞市','嵊州市'],\n            '浙江省-金华市':['婺城区','金东区','武义县','浦江县','磐安县','兰溪市','义乌市','东阳市','永康市'],\n            '浙江省-衢州市':['柯城区','衢江区','常山县','开化县','龙游县','江山市'],\n            '浙江省-舟山市':['定海区','普陀区','岱山县','嵊泗县'],\n            '浙江省-台州市':['椒江区','黄岩区','路桥区','玉环县','三门县','天台县','仙居县','温岭市','临海市'],\n            '浙江省-丽水市':['莲都区','青田县','缙云县','遂昌县','松阳县','云和县','庆元县','景宁畲族自治县','龙泉市'],\n            '安徽省-合肥市':['瑶海区','庐阳区','蜀山区','包河区','长丰县','肥东县','肥西县','庐江县','巢湖市'],\n            '安徽省-芜湖市':['镜湖区','弋江区','鸠江区','三山区','芜湖县','繁昌县','南陵县','无为县'],\n            '安徽省-蚌埠市':['龙子湖区','蚌山区','禹会区','淮上区','怀远县','五河县','固镇县'],\n            '安徽省-淮南市':['大通区','田家庵区','谢家集区','八公山区','潘集区','凤台县'],\n            '安徽省-马鞍山市':['金家庄区','花山区','雨山区','当涂县','含山县','和县'],\n            '安徽省-淮北市':['杜集区','相山区','烈山区','濉溪县'],\n            '安徽省-铜陵市':['铜官山区','狮子山区','郊区','铜陵县'],\n            '安徽省-安庆市':['迎江区','大观区','宜秀区','怀宁县','枞阳县','潜山县','太湖县','宿松县','望江县','岳西县','桐城市'],\n            '安徽省-黄山市':['屯溪区','黄山区','徽州区','歙县','休宁县','黟县','祁门县'],\n            '安徽省-滁州市':['琅琊区','南谯区','来安县','全椒县','定远县','凤阳县','天长市','明光市'],\n            '安徽省-阜阳市':['颍州区','颍东区','颍泉区','临泉县','太和县','阜南县','颍上县','界首市'],\n            '安徽省-宿州市':['埇桥区','砀山县','萧县','灵璧县','泗县'],\n            '安徽省-六安市':['金安区','裕安区','寿县','霍邱县','舒城县','金寨县','霍山县'],\n            '安徽省-亳州市':['谯城区','涡阳县','蒙城县','利辛县'],\n            '安徽省-池州市':['贵池区','东至县','石台县','青阳县'],\n            '安徽省-宣城市':['宣州区','郎溪县','广德县','泾县','绩溪县','旌德县','宁国市'],\n            '福建省-福州市':['鼓楼区','台江区','仓山区','马尾区','晋安区','闽侯县','连江县','罗源县','闽清县','永泰县','平潭县','福清市','长乐市'],\n            '福建省-厦门市':['思明区','海沧区','湖里区','集美区','同安区','翔安区'],\n            '福建省-莆田市':['城厢区','涵江区','荔城区','秀屿区','仙游县'],\n            '福建省-三明市':['梅列区','三元区','明溪县','清流县','宁化县','大田县','尤溪县','沙县','将乐县','泰宁县','建宁县','永安市'],\n            '福建省-泉州市':['鲤城区','丰泽区','洛江区','泉港区','惠安县','安溪县','永春县','德化县','金门县','石狮市','晋江市','南安市'],\n            '福建省-漳州市':['芗城区','龙文区','云霄县','漳浦县','诏安县','长泰县','东山县','南靖县','平和县','华安县','龙海市'],\n            '福建省-南平市':['延平区','顺昌县','浦城县','光泽县','松溪县','政和县','邵武市','武夷山市','建瓯市','建阳市'],\n            '福建省-龙岩市':['新罗区','长汀县','永定县','上杭县','武平县','连城县','漳平市'],\n            '福建省-宁德市':['蕉城区','霞浦县','古田县','屏南县','寿宁县','周宁县','柘荣县','福安市','福鼎市'],\n            '江西省-南昌市':['东湖区','西湖区','青云谱区','湾里区','青山湖区','南昌县','新建县','安义县','进贤县'],\n            '江西省-景德镇市':['昌江区','珠山区','浮梁县','乐平市'],\n            '江西省-萍乡市':['安源区','湘东区','莲花县','上栗县','芦溪县'],\n            '江西省-九江市':['庐山区','浔阳区','九江县','武宁县','修水县','永修县','德安县','星子县','都昌县','湖口县','彭泽县','瑞昌市','共青城市'],\n            '江西省-新余市':['渝水区','分宜县'],\n            '江西省-鹰潭市':['月湖区','余江县','贵溪市'],\n            '江西省-赣州市':['章贡区','赣县','信丰县','大余县','上犹县','崇义县','安远县','龙南县','定南县','全南县','宁都县','于都县','兴国县','会昌县','寻乌县','石城县','瑞金市','南康市'],\n            '江西省-吉安市':['吉州区','青原区','吉安县','吉水县','峡江县','新干县','永丰县','泰和县','遂川县','万安县','安福县','永新县','井冈山市'],\n            '江西省-宜春市':['袁州区','奉新县','万载县','上高县','宜丰县','靖安县','铜鼓县','丰城市','樟树市','高安市'],\n            '江西省-抚州市':['临川区','南城县','黎川县','南丰县','崇仁县','乐安县','宜黄县','金溪县','资溪县','东乡县','广昌县'],\n            '江西省-上饶市':['信州区','上饶县','广丰县','玉山县','铅山县','横峰县','弋阳县','余干县','鄱阳县','万年县','婺源县','德兴市'],\n            '山东省-济南市':['历下区','市中区','槐荫区','天桥区','历城区','长清区','平阴县','济阳县','商河县','章丘市'],\n            '山东省-青岛市':['市南区','市北区','四方区','黄岛区','崂山区','李沧区','城阳区','胶州市','即墨市','平度市','胶南市','莱西市'],\n            '山东省-淄博市':['淄川区','张店区','博山区','临淄区','周村区','桓台县','高青县','沂源县'],\n            '山东省-枣庄市':['市中区','薛城区','峄城区','台儿庄区','山亭区','滕州市'],\n            '山东省-东营市':['东营区','河口区','垦利县','利津县','广饶县'],\n            '山东省-烟台市':['芝罘区','福山区','牟平区','莱山区','长岛县','龙口市','莱阳市','莱州市','蓬莱市','招远市','栖霞市','海阳市'],\n            '山东省-潍坊市':['潍城区','寒亭区','坊子区','奎文区','临朐县','昌乐县','青州市','诸城市','寿光市','安丘市','高密市','昌邑市'],\n            '山东省-济宁市':['市中区','任城区','微山县','鱼台县','金乡县','嘉祥县','汶上县','泗水县','梁山县','曲阜市','兖州市','邹城市'],\n            '山东省-泰安市':['泰山区','岱岳区','宁阳县','东平县','新泰市','肥城市'],\n            '山东省-威海市':['环翠区','文登市','荣成市','乳山市'],\n            '山东省-日照市':['东港区','岚山区','五莲县','莒县'],\n            '山东省-莱芜市':['莱城区','钢城区'],\n            '山东省-临沂市':['兰山区','罗庄区','河东区','沂南县','郯城县','沂水县','苍山县','费县','平邑县','莒南县','蒙阴县','临沭县'],\n            '山东省-德州市':['德城区','陵县','宁津县','庆云县','临邑县','齐河县','平原县','夏津县','武城县','乐陵市','禹城市'],\n            '山东省-聊城市':['东昌府区','阳谷县','莘县','茌平县','东阿县','冠县','高唐县','临清市'],\n            '山东省-滨州市':['滨城区','惠民县','阳信县','无棣县','沾化县','博兴县','邹平县'],\n            '山东省-菏泽市':['牡丹区','曹县','单县','成武县','巨野县','郓城县','鄄城县','定陶县','东明县'],\n            '河南省-郑州市':['中原区','二七区','管城回族区','金水区','上街区','惠济区','中牟县','巩义市','荥阳市','新密市','新郑市','登封市'],\n            '河南省-开封市':['龙亭区','顺河回族区','鼓楼区','禹王台区','金明区','杞县','通许县','尉氏县','开封县','兰考县'],\n            '河南省-洛阳市':['老城区','西工区','瀍河回族区','涧西区','吉利区','洛龙区','孟津县','新安县','栾川县','嵩县','汝阳县','宜阳县','洛宁县','伊川县','偃师市'],\n            '河南省-平顶山市':['新华区','卫东区','石龙区','湛河区','宝丰县','叶县','鲁山县','郏县','舞钢市','汝州市'],\n            '河南省-安阳市':['文峰区','北关区','殷都区','龙安区','安阳县','汤阴县','滑县','内黄县','林州市'],\n            '河南省-鹤壁市':['鹤山区','山城区','淇滨区','浚县','淇县'],\n            '河南省-新乡市':['红旗区','卫滨区','凤泉区','牧野区','新乡县','获嘉县','原阳县','延津县','封丘县','长垣县','卫辉市','辉县市'],\n            '河南省-焦作市':['解放区','中站区','马村区','山阳区','修武县','博爱县','武陟县','温县','沁阳市','孟州市'],\n            '河南省-濮阳市':['华龙区','清丰县','南乐县','范县','台前县','濮阳县'],\n            '河南省-许昌市':['魏都区','许昌县','鄢陵县','襄城县','禹州市','长葛市'],\n            '河南省-漯河市':['源汇区','郾城区','召陵区','舞阳县','临颍县'],\n            '河南省-三门峡市':['湖滨区','渑池县','陕县','卢氏县','义马市','灵宝市'],\n            '河南省-南阳市':['宛城区','卧龙区','南召县','方城县','西峡县','镇平县','内乡县','淅川县','社旗县','唐河县','新野县','桐柏县','邓州市'],\n            '河南省-商丘市':['梁园区','睢阳区','民权县','睢县','宁陵县','柘城县','虞城县','夏邑县','永城市'],\n            '河南省-信阳市':['浉河区','平桥区','罗山县','光山县','新县','商城县','固始县','潢川县','淮滨县','息县'],\n            '河南省-周口市':['川汇区','扶沟县','西华县','商水县','沈丘县','郸城县','淮阳县','太康县','鹿邑县','项城市'],\n            '河南省-驻马店市':['驿城区','西平县','上蔡县','平舆县','正阳县','确山县','泌阳县','汝南县','遂平县','新蔡县'],\n            '河南省-省直辖县级行政区划':['济源市'],\n            '湖北省-武汉市':['江岸区','江汉区','硚口区','汉阳区','武昌区','青山区','洪山区','东西湖区','汉南区','蔡甸区','江夏区','黄陂区','新洲区'],\n            '湖北省-黄石市':['黄石港区','西塞山区','下陆区','铁山区','阳新县','大冶市'],\n            '湖北省-十堰市':['茅箭区','张湾区','郧县','郧西县','竹山县','竹溪县','房县','丹江口市'],\n            '湖北省-宜昌市':['西陵区','伍家岗区','点军区','猇亭区','夷陵区','远安县','兴山县','秭归县','长阳土家族自治县','五峰土家族自治县','宜都市','当阳市','枝江市'],\n            '湖北省-襄阳市':['襄城区','樊城区','襄州区','南漳县','谷城县','保康县','老河口市','枣阳市','宜城市'],\n            '湖北省-鄂州市':['梁子湖区','华容区','鄂城区'],\n            '湖北省-荆门市':['东宝区','掇刀区','京山县','沙洋县','钟祥市'],\n            '湖北省-孝感市':['孝南区','孝昌县','大悟县','云梦县','应城市','安陆市','汉川市'],\n            '湖北省-荆州市':['沙市区','荆州区','公安县','监利县','江陵县','石首市','洪湖市','松滋市'],\n            '湖北省-黄冈市':['黄州区','团风县','红安县','罗田县','英山县','浠水县','蕲春县','黄梅县','麻城市','武穴市'],\n            '湖北省-咸宁市':['咸安区','嘉鱼县','通城县','崇阳县','通山县','赤壁市'],\n            '湖北省-随州市':['曾都区','随县','广水市'],\n            '湖北省-恩施土家族苗族自治州':['恩施市','利川市','建始县','巴东县','宣恩县','咸丰县','来凤县','鹤峰县'],\n            '湖北省-省直辖县级行政区划':['仙桃市','潜江市','天门市','神农架林区'],\n            '湖南省-长沙市':['芙蓉区','天心区','岳麓区','开福区','雨花区','望城区','长沙县','宁乡县','浏阳市'],\n            '湖南省-株洲市':['荷塘区','芦淞区','石峰区','天元区','株洲县','攸县','茶陵县','炎陵县','醴陵市'],\n            '湖南省-湘潭市':['雨湖区','岳塘区','湘潭县','湘乡市','韶山市'],\n            '湖南省-衡阳市':['珠晖区','雁峰区','石鼓区','蒸湘区','南岳区','衡阳县','衡南县','衡山县','衡东县','祁东县','耒阳市','常宁市'],\n            '湖南省-邵阳市':['双清区','大祥区','北塔区','邵东县','新邵县','邵阳县','隆回县','洞口县','绥宁县','新宁县','城步苗族自治县','武冈市'],\n            '湖南省-岳阳市':['岳阳楼区','云溪区','君山区','岳阳县','华容县','湘阴县','平江县','汨罗市','临湘市'],\n            '湖南省-常德市':['武陵区','鼎城区','安乡县','汉寿县','澧县','临澧县','桃源县','石门县','津市市'],\n            '湖南省-张家界市':['永定区','武陵源区','慈利县','桑植县'],\n            '湖南省-益阳市':['资阳区','赫山区','南县','桃江县','安化县','沅江市'],\n            '湖南省-郴州市':['北湖区','苏仙区','桂阳县','宜章县','永兴县','嘉禾县','临武县','汝城县','桂东县','安仁县','资兴市'],\n            '湖南省-永州市':['零陵区','冷水滩区','祁阳县','东安县','双牌县','道县','江永县','宁远县','蓝山县','新田县','江华瑶族自治县'],\n            '湖南省-怀化市':['鹤城区','中方县','沅陵县','辰溪县','溆浦县','会同县','麻阳苗族自治县','新晃侗族自治县','芷江侗族自治县','靖州苗族侗族自治县','通道侗族自治县','洪江市'],\n            '湖南省-娄底市':['娄星区','双峰县','新化县','冷水江市','涟源市'],\n            '湖南省-湘西土家族苗族自治州':['吉首市','泸溪县','凤凰县','花垣县','保靖县','古丈县','永顺县','龙山县'],\n            '广东省-广州市':['荔湾区','越秀区','海珠区','天河区','白云区','黄埔区','番禺区','花都区','南沙区','萝岗区','增城市','从化市'],\n            '广东省-韶关市':['武江区','浈江区','曲江区','始兴县','仁化县','翁源县','乳源瑶族自治县','新丰县','乐昌市','南雄市'],\n            '广东省-深圳市':['罗湖区','福田区','南山区','宝安区','龙岗区','盐田区'],\n            '广东省-珠海市':['香洲区','斗门区','金湾区'],\n            '广东省-汕头市':['龙湖区','金平区','濠江区','潮阳区','潮南区','澄海区','南澳县'],\n            '广东省-佛山市':['禅城区','南海区','顺德区','三水区','高明区'],\n            '广东省-江门市':['蓬江区','江海区','新会区','台山市','开平市','鹤山市','恩平市'],\n            '广东省-湛江市':['赤坎区','霞山区','坡头区','麻章区','遂溪县','徐闻县','廉江市','雷州市','吴川市'],\n            '广东省-茂名市':['茂南区','茂港区','电白县','高州市','化州市','信宜市'],\n            '广东省-肇庆市':['端州区','鼎湖区','广宁县','怀集县','封开县','德庆县','高要市','四会市'],\n            '广东省-惠州市':['惠城区','惠阳区','博罗县','惠东县','龙门县'],\n            '广东省-梅州市':['梅江区','梅县','大埔县','丰顺县','五华县','平远县','蕉岭县','兴宁市'],\n            '广东省-汕尾市':['城区','海丰县','陆河县','陆丰市'],\n            '广东省-河源市':['源城区','紫金县','龙川县','连平县','和平县','东源县'],\n            '广东省-阳江市':['江城区','阳西县','阳东县','阳春市'],\n            '广东省-清远市':['清城区','佛冈县','阳山县','连山壮族瑶族自治县','连南瑶族自治县','清新县','英德市','连州市'],\n            '广东省-潮州市':['湘桥区','潮安县','饶平县'],\n            '广东省-揭阳市':['榕城区','揭东县','揭西县','惠来县','普宁市'],\n            '广东省-云浮市':['云城区','新兴县','郁南县','云安县','罗定市'],\n            '广西壮族自治区-南宁市':['兴宁区','青秀区','江南区','西乡塘区','良庆区','邕宁区','武鸣县','隆安县','马山县','上林县','宾阳县','横县'],\n            '广西壮族自治区-柳州市':['城中区','鱼峰区','柳南区','柳北区','柳江县','柳城县','鹿寨县','融安县','融水苗族自治县','三江侗族自治县'],\n            '广西壮族自治区-桂林市':['秀峰区','叠彩区','象山区','七星区','雁山区','阳朔县','临桂县','灵川县','全州县','兴安县','永福县','灌阳县','龙胜各族自治县','资源县','平乐县','荔蒲县','恭城瑶族自治县'],\n            '广西壮族自治区-梧州市':['万秀区','蝶山区','长洲区','苍梧县','藤县','蒙山县','岑溪市'],\n            '广西壮族自治区-北海市':['海城区','银海区','铁山港区','合浦县'],\n            '广西壮族自治区-防城港市':['港口区','防城区','上思县','东兴市'],\n            '广西壮族自治区-钦州市':['钦南区','钦北区','灵山县','浦北县'],\n            '广西壮族自治区-贵港市':['港北区','港南区','覃塘区','平南县','桂平市'],\n            '广西壮族自治区-玉林市':['玉州区','容县','陆川县','博白县','兴业县','北流市'],\n            '广西壮族自治区-百色市':['右江区','田阳县','田东县','平果县','德保县','靖西县','那坡县','凌云县','乐业县','田林县','西林县','隆林各族自治县'],\n            '广西壮族自治区-贺州市':['八步区','昭平县','钟山县','富川瑶族自治县'],\n            '广西壮族自治区-河池市':['金城江区','南丹县','天峨县','凤山县','东兰县','罗城仫佬族自治县','环江毛南族自治县','巴马瑶族自治县','都安瑶族自治县','大化瑶族自治县','宜州市'],\n            '广西壮族自治区-来宾市':['兴宾区','忻城县','象州县','武宣县','金秀瑶族自治县','合山市'],\n            '广西壮族自治区-崇左市':['江洲区','扶绥县','宁明县','龙州县','大新县','天等县','凭祥市'],\n            '海南省-海口市':['秀英区','龙华区','琼山区','美兰区'],\n            '海南省-省直辖县级行政区划':['白沙黎族自治县','陵水黎族自治县','乐东黎族自治县','五指山市','万宁市','东方市','文昌市','琼海市','保亭黎族苗族自治县','昌江黎族自治县','屯昌县','定安县','儋州市','临高县','澄迈县','琼中黎族苗族自治县','西沙群岛','南沙群岛','中沙群岛的岛礁及其海域'],\n            '四川省-成都市':['锦江区','青羊区','金牛区','武侯区','成华区','龙泉驿区','青白江区','新都区','温江区','金堂县','双流县','郫县','大邑县','蒲江县','新津县','都江堰市','彭州市','邛崃市','崇州市'],\n            '四川省-自贡市':['自流井区','贡井区','大安区','沿滩区','荣县','富顺县'],\n            '四川省-攀枝花市':['东区','西区','仁和区','米易县','盐边县'],\n            '四川省-泸州市':['江阳区','纳溪区','龙马潭区','泸县','合江县','叙永县','古蔺县'],\n            '四川省-德阳市':['旌阳区','中江县','罗江县','广汉市','什邡市','绵竹市'],\n            '四川省-绵阳市':['涪城区','游仙区','三台县','盐亭县','安县','梓潼县','北川羌族自治县','平武县','江油市'],\n            '四川省-广元市':['利州区','元坝区','朝天区','旺苍县','青川县','剑阁县','苍溪县'],\n            '四川省-遂宁市':['船山区','安居区','蓬溪县','射洪县','大英县'],\n            '四川省-内江市':['市中区','东兴区','威远县','资中县','隆昌县'],\n            '四川省-乐山市':['市中区','沙湾区','五通桥区','金口河区','犍为县','井研县','夹江县','沐川县','峨边彝族自治县','马边彝族自治县','峨眉山市'],\n            '四川省-南充市':['顺庆区','高坪区','嘉陵区','南部县','营山县','蓬安县','仪陇县','西充县','阆中市'],\n            '四川省-眉山市':['东坡区','仁寿县','彭山县','洪雅县','丹棱县','青神县'],\n            '四川省-宜宾市':['翠屏区','南溪区','宜宾县','江安县','长宁县','高县','珙县','筠连县','兴文县','屏山县'],\n            '四川省-广安市':['广安区','岳池县','武胜县','邻水县','华蓥市'],\n            '四川省-达州市':['通川区','达县','宣汉县','开江县','大竹县','渠县','万源市'],\n            '四川省-雅安市':['雨城区','名山县','荥经县','汉源县','石棉县','天全县','芦山县','宝兴县'],\n            '四川省-巴中市':['巴州区','通江县','南江县','平昌县'],\n            '四川省-资阳市':['雁江区','安岳县','乐至县','简阳市'],\n            '四川省-阿坝藏族羌族自治州':['汶川县','理县','茂县','松潘县','九寨沟县','金川县','小金县','黑水县','马尔康县','壤塘县','阿坝县','若尔盖县','红原县'],\n            '四川省-甘孜藏族自治州':['康定县','泸定县','丹巴县','九龙县','雅江县','道孚县','炉霍县','甘孜县','新龙县','德格县','白玉县','石渠县','色达县','理塘县','巴塘县','乡城县','稻城县','得荣县'],\n            '四川省-凉山彝族自治州':['西昌市','木里藏族自治县','盐源县','德昌县','会理县','会东县','宁南县','普格县','布拖县','金阳县','昭觉县','喜德县','冕宁县','越西县','甘洛县','美姑县','雷波县'],\n            '贵州省-贵阳市':['南明区','云岩区','花溪区','乌当区','白云区','小河区','开阳县','息烽县','修文县','清镇市'],\n            '贵州省-六盘水市':['钟山区','六枝特区','水城县','盘县'],\n            '贵州省-遵义市':['红花岗区','汇川区','遵义县','桐梓县','绥阳县','正安县','道真仡佬族苗族自治县','务川仡佬族苗族自治县','凤冈县','湄潭县','余庆县','习水县','赤水市','仁怀市'],\n            '贵州省-安顺市':['西秀区','平坝县','普定县','镇宁布依族苗族自治县','关岭布依族苗族自治县','紫云苗族布依族自治县'],\n            '贵州省-毕节市':['七星关区','大方县','黔西县','金沙县','织金县','纳雍县','威宁彝族回族苗族自治县','赫章县'],\n            '贵州省-铜仁市':['碧江区','万山区','江口县','玉屏侗族自治县','石阡县','思南县','印江土家族苗族自治县','德江县','沿河土家族自治县','松桃苗族自治县'],\n            '贵州省-黔西南布依族苗族自治州':['兴义市','兴仁县','普安县','晴隆县','贞丰县','望谟县','册亨县','安龙县'],\n            '贵州省-黔东南苗族侗族自治州':['凯里市','黄平县','施秉县','三穗县','镇远县','岑巩县','天柱县','锦屏县','剑河县','台江县','黎平县','榕江县','从江县','雷山县','麻江县','丹寨县'],\n            '贵州省-黔南布依族苗族自治州':['都匀市','福泉市','荔波县','贵定县','瓮安县','独山县','平塘县','罗甸县','长顺县','龙里县','惠水县','三都水族自治县'],\n            '云南省-昆明市':['五华区','盘龙区','官渡区','西山区','东川区','呈贡区','晋宁县','富民县','宜良县','石林彝族自治县','嵩明县','禄劝彝族苗族自治县','寻甸回族彝族自治县','安宁市'],\n            '云南省-曲靖市':['麒麟区','马龙县','陆良县','师宗县','罗平县','富源县','会泽县','沾益县','宣威市'],\n            '云南省-玉溪市':['红塔区','江川县','澄江县','通海县','华宁县','易门县','峨山彝族自治县','新平彝族傣族自治县','元江哈尼族彝族傣族自治县'],\n            '云南省-保山市':['隆阳区','施甸县','腾冲县','龙陵县','昌宁县'],\n            '云南省-昭通市':['昭阳区','鲁甸县','巧家县','盐津县','大关县','永善县','绥江县','镇雄县','彝良县','威信县','水富县'],\n            '云南省-丽江市':['古城区','玉龙纳西族自治县','永胜县','华坪县','宁蒗彝族自治县'],\n            '云南省-普洱市':['思茅区','宁洱哈尼族彝族自治县','墨江哈尼族自治县','景东彝族自治县','景谷傣族彝族自治县','镇沅彝族哈尼族拉祜族自治县','江城哈尼族彝族自治县','孟连傣族拉祜族佤族自治县','澜沧拉祜族自治县','西盟佤族自治县'],\n            '云南省-临沧市':['临翔区','凤庆县','云县','永德县','镇康县','双江拉祜族佤族布朗族傣族自治县','耿马傣族佤族自治县','沧源佤族自治县'],\n            '云南省-楚雄彝族自治州':['楚雄市','双柏县','牟定县','南华县','姚安县','大姚县','永仁县','元谋县','武定县','禄丰县'],\n            '云南省-红河哈尼族彝族自治州':['个旧市','开远市','蒙自市','屏边苗族自治县','建水县','石屏县','弥勒县','泸西县','元阳县','红河县','金平苗族瑶族傣族自治县','绿春县','河口瑶族自治县'],\n            '云南省-文山壮族苗族自治州':['文山市','砚山县','西畴县','麻栗坡县','马关县','丘北县','广南县','富宁县'],\n            '云南省-西双版纳傣族自治州':['景洪市','勐海县','勐腊县'],\n            '云南省-大理白族自治州':['大理市','漾濞彝族自治县','祥云县','宾川县','弥渡县','南涧彝族自治县','巍山彝族回族自治县','永平县','云龙县','洱源县','剑川县','鹤庆县'],\n            '云南省-德宏傣族景颇族自治州':['瑞丽市','芒市','梁河县','盈江县','陇川县'],\n            '云南省-怒江傈僳族自治州':['泸水县','福贡县','贡山独龙族怒族自治县','兰坪白族普米族自治县'],\n            '云南省-迪庆藏族自治州':['香格里拉县','德钦县','维西傈僳族自治县'],\n            '西藏自治区-拉萨市':['城关区','林周县','当雄县','尼木县','曲水县','堆龙德庆县','达孜县','墨竹工卡县'],\n            '西藏自治区-昌都地区':['昌都县','江达县','贡觉县','类乌齐县','丁青县','察雅县','八宿县','左贡县','芒康县','洛隆县','边坝县'],\n            '西藏自治区-山南地区':['乃东县','扎囊县','贡嘎县','桑日县','琼结县','曲松县','措美县','洛扎县','加查县','隆子县','错那县','浪卡子县'],\n            '西藏自治区-日喀则地区':['日喀则市','南木林县','江孜县','定日县','萨迦县','拉孜县','昂仁县','谢通门县','白朗县','仁布县','康马县','定结县','仲巴县','亚东县','吉隆县','聂拉木县','萨嘎县','岗巴县'],\n            '西藏自治区-那曲地区':['那曲县','嘉黎县','比如县','聂荣县','安多县','申扎县','索县','班戈县','巴青县','尼玛县'],\n            '西藏自治区-阿里地区':['普兰县','札达县','噶尔县','日土县','革吉县','改则县','措勤县'],\n            '西藏自治区-林芝地区':['林芝县','工布江达县','米林县','墨脱县','波密县','察隅县','朗县'],\n            '陕西省-西安市':['新城区','碑林区','莲湖区','灞桥区','未央区','雁塔区','阎良区','临潼区','长安区','蓝田县','周至县','户县','高陵县'],\n            '陕西省-铜川市':['王益区','印台区','耀州区','宜君县'],\n            '陕西省-宝鸡市':['渭滨区','金台区','陈仓区','凤翔县','岐山县','扶风县','眉县','陇县','千阳县','麟游县','凤县','太白县'],\n            '陕西省-咸阳市':['秦都区','杨陵区','渭城区','三原县','泾阳县','乾县','礼泉县','永寿县','彬县','长武县','旬邑县','淳化县','武功县','兴平市'],\n            '陕西省-渭南市':['临渭区','华县','潼关县','大荔县','合阳县','澄城县','蒲城县','白水县','富平县','韩城市','华阴市'],\n            '陕西省-延安市':['宝塔区','延长县','延川县','子长县','安塞县','志丹县','吴起县','甘泉县','富县','洛川县','宜川县','黄龙县','黄陵县'],\n            '陕西省-汉中市':['汉台区','南郑县','城固县','洋县','西乡县','勉县','宁强县','略阳县','镇巴县','留坝县','佛坪县'],\n            '陕西省-榆林市':['榆阳区','神木县','府谷县','横山县','靖边县','定边县','绥德县','米脂县','佳县','吴堡县','清涧县','子洲县'],\n            '陕西省-安康市':['汉滨区','汉阴县','石泉县','宁陕县','紫阳县','岚皋县','平利县','镇坪县','旬阳县','白河县'],\n            '陕西省-商洛市':['商州区','洛南县','丹凤县','商南县','山阳县','镇安县','柞水县'],\n            '甘肃省-兰州市':['城关区','七里河区','西固区','安宁区','红古区','永登县','皋兰县','榆中县'],\n            '甘肃省-金昌市':['金川区','永昌县'],\n            '甘肃省-白银市':['白银区','平川区','靖远县','会宁县','景泰县'],\n            '甘肃省-天水市':['秦州区','麦积区','清水县','秦安县','甘谷县','武山县','张家川回族自治县'],\n            '甘肃省-武威市':['凉州区','民勤县','古浪县','天祝藏族自治县'],\n            '甘肃省-张掖市':['甘州区','肃南裕固族自治县','民乐县','临泽县','高台县','山丹县'],\n            '甘肃省-平凉市':['崆峒区','泾川县','灵台县','崇信县','华亭县','庄浪县','静宁县'],\n            '甘肃省-酒泉市':['肃州区','金塔县','瓜州县','肃北蒙古族自治县','阿克塞哈萨克族自治县','玉门市','敦煌市'],\n            '甘肃省-庆阳市':['西峰区','庆城县','环县','华池县','合水县','正宁县','宁县','镇原县'],\n            '甘肃省-定西市':['安定区','通渭县','陇西县','渭源县','临洮县','漳县','岷县'],\n            '甘肃省-陇南市':['武都区','成县','文县','宕昌县','康县','西和县','礼县','徽县','两当县'],\n            '甘肃省-临夏回族自治州':['临夏市','临夏县','康乐县','永靖县','广河县','和政县','东乡族自治县','积石山保安族东乡族撒拉族自治县'],\n            '甘肃省-甘南藏族自治州':['合作市','临潭县','卓尼县','舟曲县','迭部县','玛曲县','碌曲县','夏河县'],\n            '青海省-西宁市':['城东区','城中区','城西区','城北区','大通回族土族自治县','湟中县','湟源县'],\n            '青海省-海东地区':['平安县','民和回族土族自治县','乐都县','互助土族自治县','化隆回族自治县','循化撒拉族自治县'],\n            '青海省-海北藏族自治州':['门源回族自治县','祁连县','海晏县','刚察县'],\n            '青海省-黄南藏族自治州':['同仁县','尖扎县','泽库县','河南蒙古族自治县'],\n            '青海省-海南藏族自治州':['共和县','同德县','贵德县','兴海县','贵南县'],\n            '青海省-果洛藏族自治州':['玛沁县','班玛县','甘德县','达日县','久治县','玛多县'],\n            '青海省-玉树藏族自治州':['玉树县','杂多县','称多县','治多县','囊谦县','曲麻莱县'],\n            '青海省-海西蒙古族藏族自治州':['格尔木市','德令哈市','乌兰县','都兰县','天峻县'],\n            '宁夏回族自治区-银川市':['兴庆区','西夏区','金凤区','永宁县','贺兰县','灵武市'],\n            '宁夏回族自治区-石嘴山市':['大武口区','惠农区','平罗县'],\n            '宁夏回族自治区-吴忠市':['利通区','红寺堡区','盐池县','同心县','青铜峡市'],\n            '宁夏回族自治区-固原市':['原州区','西吉县','隆德县','泾源县','彭阳县'],\n            '宁夏回族自治区-中卫市':['沙坡头区','中宁县','海原县'],\n            '新疆维吾尔自治区-乌鲁木齐市':['天山区','沙依巴克区','新市区','水磨沟区','头屯河区','达坂城区','米东区','乌鲁木齐县'],\n            '新疆维吾尔自治区-克拉玛依市':['独山子区','克拉玛依区','白碱滩区','乌尔禾区'],\n            '新疆维吾尔自治区-吐鲁番地区':['吐鲁番市','鄯善县','托克逊县'],\n            '新疆维吾尔自治区-哈密地区':['哈密市','巴里坤哈萨克自治县','伊吾县'],\n            '新疆维吾尔自治区-昌吉回族自治州':['昌吉市','阜康市','呼图壁县','玛纳斯县','奇台县','吉木萨尔县','木垒哈萨克自治县'],\n            '新疆维吾尔自治区-博尔塔拉蒙古自治州':['博乐市','精河县','温泉县'],\n            '新疆维吾尔自治区-巴音郭楞蒙古自治州':['库尔勒市','轮台县','尉犁县','若羌县','且末县','焉耆回族自治县','和静县','和硕县','博湖县'],\n            '新疆维吾尔自治区-阿克苏地区':['阿克苏市','温宿县','库车县','沙雅县','新和县','拜城县','乌什县','阿瓦提县','柯坪县'],\n            '新疆维吾尔自治区-克孜勒苏柯尔克孜自治州':['阿图什市','阿克陶县','阿合奇县','乌恰县'],\n            '新疆维吾尔自治区-喀什地区':['喀什市','疏附县','疏勒县','英吉沙县','泽普县','莎车县','叶城县','麦盖提县','岳普湖县','伽师县','巴楚县','塔什库尔干塔吉克自治县'],\n            '新疆维吾尔自治区-和田地区':['和田市','和田县','墨玉县','皮山县','洛浦县','策勒县','于田县','民丰县'],\n            '新疆维吾尔自治区-伊犁哈萨克自治州':['伊宁市','奎屯市','伊宁县','察布查尔锡伯自治县','霍城县','巩留县','新源县','昭苏县','特克斯县','尼勒克县'],\n            '新疆维吾尔自治区-塔城地区':['塔城市','乌苏市','额敏县','沙湾县','托里县','裕民县','和布克赛尔蒙古自治县'],\n            '新疆维吾尔自治区-阿勒泰地区':['阿勒泰市','布尔津县','富蕴县','福海县','哈巴河县','青河县','吉木乃县'],\n            '新疆维吾尔自治区-自治区直辖县级行政区划':['石河子市','阿拉尔市','图木舒克市','五家渠市']\n         }\n     };\n\n    if (CMPT){\n        NEJ.P('nej.ut')._$$RegionCacheZH = _p._$$CacheRegionZH;\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/dispatcher/dispatcher.2.js",
    "content": "// link to util/dispatcher/dispatcher for compatible\n// use util/dispatcher/dispatcher for new project\nNEJ.define(['./dispatcher.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/dispatcher/dispatcher.js",
    "content": "/*\n * ------------------------------------------\n * 模块调度器实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/dispatcher/dispatcher */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'base/util',\n    'util/history/history',\n    'util/template/tpl',\n    'util/event',\n    './dsp/util.js',\n    './dsp/node.js',\n    './dsp/group.js',\n    './dsp/single.js',\n    './module.js',\n    '{platform}dispatcher.js'\n],function(NEJ,_k,_e,_v,_u,_t0,_t1,_t2,_t3,_t4,_t5,_t6,_t7,_h,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 调度器对象，项目仅允许实例化一个调度器\n     *\n     * 代码举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/template/tpl',\n     *     'util/dispatcher/dispatcher'\n     * ],function(_e,_p){\n     *     // 取调度器实例\n     *     var dispatcher = _p._$$Dispatcher._$getInstance();\n     *\n     *     // 添加规则\n     *     dispatcher._$rule({\n     *         title:{\n     *             '/m/a':'模块标题',\n     *             '/m/b':'模块标题'\n     *         },\n     *         rewrite:[\n     *             {'/m/a':''},\n     *             {'/m/b':/^\\/m\\/d.*$/i}\n     *         ]\n     *     });\n     *\n     *     // 注册模块\n     *     dispatcher._$regist({\n     *         '/m/a':'/m/a.html',\n     *         '/m/b':'/m/b.html',\n     *         '/m/c':'/m/c.html'\n     *     });\n     *\n     *     // 激活调度器\n     *     dispatcher._$active();\n     *\n     *     // 以上逻辑也可通过构造参数方式输入\n     *     var dispatcher = _p._$$Dispatcher._$getInstance({\n     *         rules:{\n     *             title:{\n     *                 '/m/a':'模块标题',\n     *                 '/m/b':'模块标题'\n     *             },\n     *             rewrite:[\n     *                {'/m/a':''},\n     *                {'/m/b':/^\\/m\\/b.*$/i}\n     *             ]\n     *         },\n     *         modules:{\n     *             '/m/a':'/m/a.html',\n     *             '/m/b':'/m/b.html',\n     *             '/m/c':'/m/c.html'\n     *         },\n     *         onbeforechange:function(_event){\n     *             // 根据dispatcher规则解析出来的路径信息\n     *             // _event.path   <--- 模块UMI\n     *             // _event.href   <--- 路径完整信息\n     *             // _event.query  <--- 查询参数信息\n     *             // 可以通过修改以上参数调整调度模块\n     *         }\n     *     })\n     *     dispatcher._$active();\n     *\n     *     // 调度器激活前需确保当前可能出现的模块均已注册到调度器中\n     *     // 实际应用中常出现以下情况\n     *     var dispatcher = _$$Dispatcher._$getInstance({\n     *         modules:{\n     *             '/m/a':'/m/a.html',\n     *             '/m/b':'/m/b.html',\n     *             '/m/c':'/m/c.html'\n     *         }\n     *     });\n     *     // 先解析页面模板，因为在解析模板的过程中可能会有模块构造器的注册逻辑\n     *     // 注册模块构造器的优先级要比注册模板文件地址的优先级高，\n     *     // 因此必须确保此处可能出现注册构造器的逻辑已处理以避免调度器激活时发出模块模板文件的请求\n     *     // 比如 在模板内联了'/m/c'模块的相关模板（包括样式、结构和逻辑），如果此处不先解析模板，\n     *     // 则在调度器激活时，调度器会识别出'/m/c'对应的是模板文件'/m/c.html'，因此回去加载这个文件，\n     *     // 而实际上这个文件的内容已内联在页面的模板中，因此会产生额外的请求开销\n     *     _e._$parseTemplate('template-box');\n     *     // 激活调度器\n     *     dispatcher._$active();\n     * });\n     * ```\n     *\n     * @class    module:util/dispatcher/dispatcher._$$Dispatcher\n     * @extends  module:util/event._$$EventTarget\n     *\n     * @param    {Object}  config  - 可选配置参数，已处理的参数列表如下\n     * @property {Object}  modules - 模块配置\n     * @property {Object}  rules   - 规则配置\n     * @property {Boolean} rest    - 是否支持REST风格的UMI解析\n     */\n    /**\n     * 行为解析之前触发事件，一般用于解析节点中行为相关信息\n     *\n     * 结构举例\n     * ```html\n     * <div data-res-id=\"xxxx\"\n     *      data-res-type=\"2\"\n     *      data-res-action=\"show\"\n     *      data-res-data=\"a=aaaa&b=bbbb&c=cccc\">\n     *   <!-- content here -->\n     * </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/dispatcher/dispatcher'\n     * ],function(_p){\n     *     // startup dispatcher\n     *     _p._$startup({\n     *         // ...\n     *         onbeforeaction:function(_event){\n     *             var _data = _e._$dataset(_event.target,'resData');\n     *             // _event.result -> {id:'xxxx',type:'2',action:'show'}\n     *             _event.result.param = _data;\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @event    module:util/dispatcher/dispatcher._$$Dispatcher#onbeforeaction\n     * @param    {Object} event  - 行为相关信息\n     * @property {Node}   target - 触发行为的节点对象\n     * @property {Event}  event  - 原始事件对象\n     * @property {Object} result - 行为相关信息\n     */\n    /**\n     * 地址变换之前触发事件\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/dispatcher/dispatcher'\n     * ],function(_p){\n     *     // startup dispatcher\n     *     _p._$startup({\n     *         // ...\n     *         onbeforechange:function(_event){\n     *             // _event -> {path:'/m/a',href:'http://a.b.com/m/a',query:{a:'aaaaa'}}\n     *             var _umi = _event.path||'';\n     *             if (!!_umi&&_umi.indexOf('/?')<0&&_umi.indexOf('/m')<0){\n     *                 _event.path = '/m'+_umi;\n     *             }\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @event    module:util/dispatcher/dispatcher._$$Dispatcher#onbeforechange\n     * @param    {Object} event - 地址信息\n     * @property {String} path  - 路径信息，不带查询参数\n     * @property {String} href  - 完整路径，带查询参数\n     * @property {Object} query - 查询参数解析出来的对象\n     */\n    /**\n     * 模块无法匹配时触发事件\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/dispatcher/dispatcher'\n     * ],function(_p){\n     *     // startup dispatcher\n     *     _p._$startup({\n     *         // ...\n     *         onnotfound:function(_event){\n     *             // _event -> {path:'/m/a',href:'http://a.b.com/m/a'}\n     *             _event.stopped = !0;\n     *             location.href = '/404';\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @event    module:util/dispatcher/dispatcher._$$Dispatcher#onnotfound\n     * @param    {Object}  event - 地址信息\n     * @property {String}  path  - 路径信息，不带查询参数\n     * @property {String}  href  - 完整路径，带查询参数\n     * @property {Boolean} stopped - 是否阻止进一步调度器逻辑\n     */\n    _p._$$Dispatcher = _k._$klass();\n    _pro = _p._$$Dispatcher._$extend(_t2._$$EventTarget);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__super();\n        var _seed = _u._$uniqueID();\n        this.__pbseed = 'pb-'+_seed;\n        this.__pvseed = 'pv-'+_seed;\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        // temporary params\n        // umi - input params\n        this.__dtmp = {};\n        this.__rest = !!_options.rest;\n        this.__root = _t4._$$Node._$allocate();\n        // config map\n        // - m   config for module, umi:{title:'xxx' ... }\n        // - mg  umi to group id map, umi:gid\n        // - r   config for rewrite, [{umi:regexp or string or function or array}]\n        // - rr  build-in rewrite\n        // - al  alias map\n        // - am  actions map, {click:[],dblclick:[]}\n        this.__config = {m:{},mg:{},r:[],rr:{},al:{},am:{}};\n        this.__groups = {};\n        // for public module umi manager\n        this.__doBuildGroup(this.__pbseed);\n        // for private module umi manager\n        this.__groups[this.__pvseed] =\n            _t5._$$GroupManager._$allocate({\n                root:this.__root,\n                dispatcher:this\n            });\n        // bugfix hash title for ie with flash\n        _h.__doFixHashTitle(document.title);\n        // add listeners\n        this.__doInitDomEvent([[\n            location,'urlchange',\n            this.__onURLChange._$bind(this)\n        ]]);\n        this.__super(_options);\n        // init config\n        this._$rule(_options.rules);\n        this._$regist(_options.modules);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = (function(){\n        var _doRecycle = function(_group,_key,_map){\n            delete _map[_key];\n            _group._$recycle();\n        };\n        return function(){\n            delete this.__config;\n            this.__root = this.__root._$recycle();\n            _u._$loop(this.__groups,_doRecycle);\n            this.__super();\n        };\n    })();\n    /**\n     * 设置模块配置信息\n     *\n     * @protected\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#__setModuleConf\n     * @param  {String}   arg0 - 模块UMI\n     * @param  {String}   arg1 - 配置类别\n     * @param  {Variable} arg2 - 配置信息\n     * @return {Void}\n     */\n    _pro.__setModuleConf = function(_umi,_key,_value){\n        var _mconf = this.__config.m[_umi];\n        if (!_mconf){\n            _mconf = {};\n            this.__config.m[_umi] = _mconf;\n        }\n        _mconf[_key] = _value;\n    };\n    /**\n     * 取模块配置信息\n     *\n     * @protected\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#__getModuleConf\n     * @param  {String} arg0 - 模块UMI\n     * @param  {String} arg1 - 配置标识\n     * @return {String}        配置信息\n     */\n    _pro.__getModuleConf = function(_umi,_key){\n        var _mconf = this.__config.m[_umi];\n        return !_mconf?'':_mconf[_key];\n    };\n    /**\n     * 构建分组管理器\n     *\n     * @protected\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#__doBuildGroup\n     * @param  {String} arg0 - 管理器标识\n     * @return {module:util/dispatcher/dsp/single._$$GroupManagerSingle} 分组管理器实例\n     */\n    _pro.__doBuildGroup = function(_gid){\n        if (!_gid) return;\n        var _group = this.__groups[_gid];\n        if (!_group){\n            _group = _t6._$$GroupManagerSingle._$allocate({\n                root:this.__root,\n                dispatcher:this,\n                classed:_gid==this.__pbseed\n            });\n            this.__groups[_gid] = _group;\n        }\n        return _group;\n    };\n    /**\n     * 添加UMI至分组管理器\n     *\n     * @protected\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#__doAddUMI2Group\n     * @param  {String} arg0 - 模块UMI\n     * @param  {String} arg1 - 分组标识\n     * @return {Void}\n     */\n    _pro.__doAddUMI2Group = function(_umi,_gid){\n        var _group = this.__doBuildGroup(_gid);\n        if (!_group){\n            _gid = _t3._$isUMIPrivate(_umi)\n                 ? this.__pvseed : this.__pbseed;\n            _group = this.__groups[_gid];\n        }\n        _group._$addUMI(_umi);\n        this.__config.mg[_umi] = _gid;\n    };\n    /**\n     * 重写UMI规则\n     *\n     * @protected\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#__doRewriteUMI\n     * @param  {String} arg0 - 模块UMI\n     * @return {String}        重写后模块UMI\n     */\n    _pro.__doRewriteUMI = (function(){\n        var _reg = /\\$\\d/;\n        return function(_umi,_href){\n            var _result;\n            _u._$forIn(this.__config.r,\n                function(_config){\n                    _u._$forIn(_config,\n                        function(_value,_key){\n                            // fix safari array bug #{404:'/'}\n                            if (_value==null){\n                                return;\n                            }\n                            // function\n                            if (_u._$isFunction(_value)){\n                                var _ret = !1;\n                                try{\n                                    _ret = _value.call(null,{\n                                        umi:_umi,\n                                        href:_href\n                                    });\n                                }catch(ex){\n                                    // ignore\n                                }\n                                if (!!_ret){\n                                    _result = _key;\n                                    return !0;\n                                }\n                            }\n                            // array\n                            if (_u._$isArray(_value)){\n                                var _index = _u._$indexOf(_value,function(v){\n                                    return v===_umi||v===_href;\n                                });\n                                if (_index>=0){\n                                    _result = _key;\n                                    return !0;\n                                }\n                            }\n                            // regexp\n                            if (!!_value.test&&(\n                                  _value.test(_umi)||\n                                  _value.test(_href))){\n                                // /^\\/a\\/([\\d]+)\\/([\\d]+)\\/$/ ---> /a/?p=$1&k=$2\n                                // /a/123/456/ ---> /a/?p=123&k=456\n                                _result = _reg.test(_key)?_umi.replace(_value,_key):_key;\n                                return !0;\n                            }\n                            // string\n                            if (_value===_umi||\n                                _value===_href){\n                                _result = _key;\n                                return !0;\n                            }\n                        });\n                    return !!_result;\n                });\n            return _result||_umi;\n        };\n    })();\n    /**\n     * URL变化触发事件\n     *\n     * @protected\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#__onURLChange\n     * @param  {Object} arg0 - 地址信息\n     * @return {Void}\n     */\n    _pro.__onURLChange = (function(){\n        var _trim = /(?:^\\/+)|(?:\\/+$)/gi,\n            _reg0 = /#(\\$.*?)$/,\n            _reg1 = /\\/$/;\n        var _doParseRestParam = function(_umi,_node){\n            var _path = _node._$getPath(),\n                _umi = _umi.replace(_path,'')\n                           .replace(_trim,'');\n            return _umi.split('/');\n        };\n        var _doTryGroupId = function(_umi,_map){\n            // TODO improve performance\n            var _value,\n                _arr = _umi.split('/');\n            while(_arr.length>0){\n                if (!_arr[_arr.length-1]){\n                    _arr.pop();\n                }else{\n                    _arr[_arr.length-1] = '';\n                }\n                _value = _map[_arr.join('/')];\n                if (!!_value) return _value;\n            }\n            return '';\n        };\n        return function(_location){\n            // ignore if hash start with $\n            if (_location.path.indexOf('$')==0) return;\n            // check input param\n            var _input = this.__dtmp[_location.path];\n            delete this.__dtmp[_location.path];\n            // check outer logic\n            this._$dispatchEvent('onbeforechange',_location);\n            var _umi = this.__doRewriteUMI(\n                    _location.path,\n                    _location.href\n                ),\n                _gid = this.__config.mg[_umi];\n            // try umi from rest path\n            if (!_gid&&this.__rest){\n                _gid = _doTryGroupId(\n                       _umi,this.__config.mg);\n            }\n            // public umi not registed\n            if (!_gid&&!_t3._$isUMIPrivate(_umi)){\n                // check 404 callback\n                var event = {\n                    path:_umi,\n                    href:_location.href\n                };\n                this._$dispatchEvent('onnotfound',event);\n                if (event.stopped){\n                    return;\n                }\n                // go 404 config\n                _umi = this.__config.rr['404'];\n                _gid = this.__config.mg[_umi];\n            }\n            // try umi from rest path\n            if (!_gid&&this.__rest){\n                _gid = _doTryGroupId(\n                       _umi,this.__config.mg);\n            }\n            if (!_gid) return;\n            // save dispatch event\n            var _node = _t3._$getNodeByUMI(this.__root,_umi),\n                _prst = null;\n            if (this.__rest){\n                _prst = _doParseRestParam(_umi,_node);\n                // try rest umi end with /\n                if (!_reg1.test(_umi)&&\n                    !!this.__config.mg[_umi+'/']){\n                    _node = _node._$getChildByName('/');\n                }\n            }\n            // fix umi for module\n            var _source = _umi;\n            _umi = _node._$getPath();\n            _node._$getData().event = {\n                target:_umi,\n                source:_source,\n                href:_location.href,\n                param:_location.query,\n                input:_input,\n                prest:_prst,\n                clazz:this.__getModuleConf(_umi,'clazz'),\n                pos:_reg0.test(_location.href)?RegExp.$1:''\n            };\n            // dispatch module\n            var event = {\n                title:this.__getModuleConf(_source,'title')\n            };\n            this._$dispatchEvent('ontitlechange',event);\n            if (!!event.title){\n                document.title = event.title;\n            }\n            this.__groups[_gid]._$dispatchUMI(_umi);\n        };\n    })();\n    /**\n     * 点击代理\n     *\n     * @protected\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#__onClickDelegate\n     * @param  {Event} arg0 - 点击事件对象\n     * @return {Void}\n     */\n    _pro.__onClickDelegate = (function(){\n        // check event need delegated\n        var _doCheckUMI = function(_url,_href){\n            if (!_url) return;\n            var _info = location.parse(_url);\n            this._$dispatchEvent('onbeforechange',_info);\n            var _umi = this.__doRewriteUMI(\n                _info.path,_href||_info.href\n            );\n            return this.__groups[this.__pbseed]._$hasUMI(_umi);\n        };\n        var _doParseUMI = function(_node){\n            // parse data-href\n            var _umi = _e._$dataset(_node,'href');\n            if (!!_umi) return _umi;\n            // parse href without data-not-umi\n            var _href = _e._$attr(_node,'href');\n            if (!!_href&&!_e._$dataset(_node,'notUmi')){\n                // umi in hash\n                var _arr = _href.split('#');\n                _arr.shift();\n                var _umi = _arr.join('#');\n                if (_doCheckUMI.call(this,_umi,_href)){\n                    return _umi;\n                }\n                // umi in path\n                if (_doCheckUMI.call(this,_href)){\n                    var _info = location.parse(_href);\n                    return _info.path+'?'+\n                           _u._$object2query(_info.query);\n                }\n            }\n        };\n        var _isNode = function(_node){\n            return !!_doParseUMI.call(this,_node);\n        };\n        return function(_event){\n            var _element = _v._$getElement(\n                _event,_isNode._$bind(this)\n            );\n            if (!!_element){\n                _v._$stopDefault(_event);\n                this._$redirect(\n                    _doParseUMI.call(this,_element)\n                );\n            }\n        };\n    })();\n    /**\n     * 解析行为代理\n     *\n     * @protected\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#__onActionDelegate\n     * @param  {Event} arg0 - 点击事件对象\n     * @return {Void}\n     */\n    _pro.__onActionDelegate = function(_event){\n        var _am = this.__config.am,\n            _conf = _am[_event.type];\n        if (!_conf) return;\n        // has action delegate\n        var _element = _v._$getElement(_event,'d:resAction');\n        if (!_element) return;\n        var _action = _e._$dataset(_element,'resAction')||'',\n            _handler = _conf[_action.toLowerCase()];\n        if (!_handler) return;\n        // has action node\n        var _options = {\n            action:_action,\n            target:_element,\n            id:_e._$dataset(_element,'resId'),\n            type:_e._$dataset(_element,'resType'),\n            extra:_e._$dataset(_element,'resExtra')\n        };\n        // do other parse\n        this._$dispatchEvent('onbeforeaction',{\n            event:_event,\n            target:_element,\n            result:_options\n        });\n        // trigger action\n        _handler.call(this,_options);\n    };\n    /**\n     * 添加调度规则\n     *\n     * 脚本举例\n     * ```javascript\n     * // 配置模块标题\n     * dispatcher._$rule('title',{\n     *     '/m/a':'模块标题',\n     *     '/m/b':'模块标题',\n     *     '/m/c':'模块标题'\n     * });\n     *\n     * // 配置别名\n     * dispatcher._$rule('alias',{\n     *     'a':'/m/a',\n     *     'b':['/m/b','/m/bb'],\n     *     'c':'/m/c'\n     * });\n     *\n     * // 配置与匹配顺序无关重写规则\n     * // 重写规则配置结构：{ 目标UMI:重写规则 }\n     * // 重写规则可以是字符串（全字符匹配）或者正则表达式\n     * dispatcher._$rule('rewrite',{\n     *     '/m/b':/^\\/m\\/b.*$/i,\n     *     '/m/c':'/m/d'\n     * });\n     *\n     * // 批量配置重写规则\n     * // 重写规则内置匹配代码支持\n     * // 404 - 当模块不存在时重定向的模块UMI\n     * dispatcher._$rule([\n     *     {'/m/a':'/m/','/m/c':'/m/d'},  // <---- 此处两条规则匹配与顺序无关\n     *     {'/m/b':/^\\/m\\/b.*$/i},\n     *     {'404':'/m/a'}                 // <---- 模块不存在时定向到/m/a模块\n     * ]);\n     *\n     * // 配置行为，默认为click行为，模块中通过options.input接收配置信息\n     * // 默认行为信息解析节点上的以下内容：\n     * // data-res-id         资源标识\n     * // data-res-type       资源类型\n     * // data-res-action     对资源操作的行为\n     * // data-res-extra      其他信息，如a=aaa&b=bbb或者{\"a\":\"aaa\",\"b\":\"bbb\"}等等，根据实际情况配置\n     * dispatcher._$rule('action',{\n     *     'show':'/m/a',    // 等价于dispatcher._$redirect('/m/a')\n     *     'play':function(_options){\n     *         // _options -> {type:'xxxx',id:'xxxx'}\n     *         // TODO something\n     *         // 返回结果如果为：\n     *         // undefined/null  表明业务逻辑已在此函数内处理完毕\n     *         // string          表明返回的是UMI，后续会调用_$redirect到该UMI\n     *     },\n     *     'fav':{\n     *         event:'dblclick',\n     *         value:'/m/b' // or function\n     *     }\n     * });\n     *\n     * // 批量配置标题和重写规则\n     * dispatcher._$rule({\n     *     'title':{\n     *         '/m/a':'模块标题',\n     *         '/m/b':'模块标题',\n     *         '/m/c':'模块标题'\n     *     },\n     *     'rewrite':{\n     *         '/m/b':/^\\/m\\/b.*$/i,\n     *         '/m/c':'/m/d'\n     *     },\n     *     'alias':{\n     *         'a':'/m/a',\n     *         'b':['/m/b','/m/bb'],\n     *         'c':'/m/c'\n     *     },\n     *     action:{\n     *         'show':'/m/a',\n     *         'play':function(_options){\n     *             // TODO something\n     *         }\n     *     }\n     * });\n     * ```\n     *\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#_$rule\n     * @param  {String}       arg0 - 规则类型，支持类型: title/rewrite/alias/action\n     * @param  {Object|Array} arg1 - 规则配置，对于重写规则存在匹配的先后顺序\n     * @return {Void}\n     */\n    _pro._$rule = (function(){\n        var _buildin = ['404'];\n        // regist rule\n        var _doRegistRule = function(_config,_key){\n            this._$rule(_key,_config);\n        };\n        // regist title\n        var _doRegistTitle = function(_title,_umi){\n            this.__setModuleConf(_umi,'title',_title);\n        };\n        // regist alias map\n        var _doRegistAlias = function(_umi,_alias){\n            this.__config.al[_alias] = _umi;\n        };\n        // regist rewrite\n        var _doRegistRewrite = function(_config){\n            if (!_config) return;\n            this.__config.r.push(_config);\n            // parse build-in rewrite rule\n            _u._$forEach(_buildin,\n                function(_key){\n                    if (!_config[_key]) return;\n                    this.__config.rr[_key] = _config[_key];\n                    delete _config[_key];\n                },this);\n        };\n        // regist actions\n        var _doRegistAction = function(_action,_name){\n            var _am = this.__config.am;\n            // parse event/handler from object\n            var _event = 'click',\n                _handler = _action,\n                _name = (_name||'').toLowerCase();\n            if (_u._$isObject(_action)){\n                _event = _action.event||_event;\n                _handler = _action.value;\n            }\n            // parse handler\n            if (_u._$isString(_handler)){\n                _handler = function(_umi,_options){\n                    this._$redirect(_umi,{\n                        force:!0,\n                        input:_options\n                    });\n                }._$bind(this,_handler);\n            }else if(_u._$isFunction(_handler)){\n                _handler = _handler._$aop(null,function(_event){\n                    var _result = _event.value;\n                    if (_u._$isString(_result)){\n                        this._$redirect(_result,{\n                            force:!0,\n                            input:_event.args[0]\n                        });\n                    }\n                }._$bind(this));\n            }\n            // push handler to cache\n            if (_u._$isFunction(_handler)){\n                // add event delegate\n                if (!_am[_event]) {\n                    this.__doInitDomEvent([[\n                        document,_event,\n                        this.__onActionDelegate._$bind(this)\n                    ]]);\n                    _am[_event] = {};\n                }\n                _am[_event][_name] = _handler;\n            }\n        };\n        // rule parse function map\n        var _fmap = {\n            title:function(_config){\n                _u._$loop(_config,\n                   _doRegistTitle,this);\n            },\n            rewrite:function(_config){\n                if (!_u._$isArray(_config)){\n                    _doRegistRewrite.call(this,_config);\n                }else{\n                    _u._$forEach(\n                        _config,\n                        _doRegistRewrite,this\n                    );\n                }\n            },\n            alias:function(_config){\n                _u._$loop(\n                    _config,\n                    _doRegistAlias,this\n                );\n            },\n            action:function(_config){\n                _u._$loop(\n                    _config,\n                    _doRegistAction,this\n                );\n            }\n        };\n        return function(_key,_config){\n            if (_u._$isArray(_key)){\n                _config = _key;\n                _key = 'rewrite';\n            }else if (!_u._$isString(_key)){\n                _u._$forIn(_key,_doRegistRule,this);\n                return;\n            }\n            // regist rule by type\n            (_fmap[_key]||_f).call(this,_config);\n        };\n    })();\n    /**\n     * 注册UMI与模块的对应关系\n     *\n     * 脚本举例\n     * ```javascript\n     * // 注册模块的模板文件路径\n     * dispatcher._$regist('/m/a/','/m/a.html');\n     *\n     * // 注册模块的配置信息，包括标题和文件路径\n     * dispatcher._$regist('/m/a/',{\n     *     title:'模块标题',\n     *     clazz:'g-ma',\n     *     module:'/m/a.html'\n     * });\n     *\n     * // 注册模块的配置信息，包括标题和模块构造器\n     * dispatcher._$regist('/m/a/',{\n     *     title:'模块标题',\n     *     clazz:'g-ma',\n     *     module:np.m._$$ModuleA\n     * });\n     *\n     * // 注册模块的构造器\n     * dispatcher._$regist('/m/a/',np.m._$$ModuleA);\n     *\n     * // 注册私有模块指定分组ID，同一分组的私有模块调度时仅显示一个模块\n     * dispatcher._$regist('/?/a/b/',{\n     *     gid:'234567890',\n     *     module:'/m/a/b.html'\n     * });\n     *\n     * // 批量注册模块\n     * dispatcher._$regist({\n     *     '/m/a/':'/m/a.html',\n     *     '/m/a/a':np.m._$$ModuleAA,\n     *     '/m/b/':{\n     *               title:'模块标题',\n     *               clazz:'g-mb',\n     *               module:'/m/b.html'\n     *             },\n     *     '/m/c/':{\n     *               title:'模块标题',\n     *               clazz:'g-mc',\n     *               module:np.m._$$ModuleC\n     *             },\n     *     '/?/m/a/':'/m/s/a.html',\n     *     '/?/m/a/a':np.m.s._$$ModuleAA,\n     *     '/?/m/b/':{\n     *                 gid:'abc',\n     *                 title:'模块标题',\n     *                 module:'/m/b.html'\n     *               },\n     *     '/?/m/c/':{\n     *                 gid:'abc',\n     *                 title:'模块标题',\n     *                 module:np.m._$$ModuleC\n     *               },\n     * });\n     * ```\n     *\n     * @method   module:util/dispatcher/dispatcher._$$Dispatcher#_$regist\n     * @param    {String|Object} arg0      - 统一模块标识或者模块批量添加信息\n     * @param    {String|Object|module:util/dispatcher/module._$$ModuleAbstract}\n     *                           arg1      - 模块构造或者模块路径或者模块配置信息\n     * @property {String}        gid       - 指定模块分组，仅对私有模块有效，对外模块忽略此配置\n     * @property {String}        title     - 模块标题，显示模块时修改页面的标题\n     * @property {String}        clazz     - 模块切换时body样式调整，仅对公共模块有效\n     * @property {String|module:util/dispatcher/module._$$ModuleAbstract}\n     *                           module    - 指定模块对应的模板文件地址或者模块的构造函数\n     * @property {Object}        composite - 组合模块容器对应关系,{pid:umi},其中pid为umi对应模块的容器\n     * @property {Object}        config    - 模块构建配置信息，在模块的init/reset/dobuild时可以获取到的配置信息\n     * @return   {Void}\n     */\n    _pro._$regist = (function(){\n        // regist single module\n        var _doRegistUMI = function(_config,_umi){\n            this._$regist(_umi,_config);\n        };\n        // check if module constructor\n        var _isModuleClass = function(_module){\n            return !!_module&&!!_module._$extend;\n        };\n        // function body\n        return function(_umi,_config){\n            // batch regist\n            if (!_u._$isString(_umi)){\n                _u._$forIn(_umi,_doRegistUMI,this);\n                return;\n            }\n            // regist module with umi\n            var _data = _t3._$appendNodeByUMI(\n                    this.__root,_umi\n                )._$getData(),\n                _module = _data.module;\n            // ignore if\n            // - module constructor is registed\n            // - module is instanced\n            if (_t3._$isModule(_module)||\n                _isModuleClass(_module)){\n                return;\n            }\n            // parse conifg\n            var _gid = this.__config.mg[_umi],_module;\n            if (_u._$isString(_config)||\n                _isModuleClass(_config)){\n                // config is module template file or module constructor\n                _module = _config;\n            }else{\n                // conifg is module information\n                _config = _config||_o;\n                _gid = _config.gid;\n                _module = _config.module;\n                // cache module title\n                if (!!_config.title){\n                    this.__setModuleConf(\n                        _umi,'title',\n                        _config.title\n                    );\n                }\n                // cache module clazz\n                if (!!_config.clazz){\n                    this.__setModuleConf(\n                        _umi,'clazz',\n                        _config.clazz\n                    );\n                }\n                // cache module composite\n                if (!!_config.composite){\n                    _data.composite = _config.composite;\n                }\n                // cache module build config\n                if (!!_config.config){\n                    _data.config = _config.config;\n                }\n            }\n            // save module\n            this.__doAddUMI2Group(_umi,_gid);\n            _data.module = _module;\n        };\n    })();\n    /**\n     * 发送消息，消息模式\n     *\n     * * 0 - 目标消息【默认】，只有目标节点收到消息\n     * * 1 - 目标广播，从根节点至路目标节点径上的节点收到消息\n     * * 2 - 群体广播，节点下所有子孙子孙节点收到消息\n     *\n     * @method   module:util/dispatcher/dispatcher._$$Dispatcher#_$message\n     * @param    {Object} arg0 - 消息相关信息\n     * @property {String} to   - 消息目标UMI\n     * @property {String} from - 消息来源UMI\n     * @property {Object} data - 消息数据\n     * @property {Number} mode - 消息模式\n     * @return   {Void}\n     */\n    _pro._$message = (function(){\n        // send message\n        var _doSendMessage = function(_node,_message){\n            var _module = _node._$getData().module;\n            if (_t3._$isModule(_module)){\n                _module._$dispatchEvent('onmessage',_message);\n            }\n        };\n        // message mode function\n        var _fmap = [\n            _doSendMessage,\n            // send message to every node in target path\n            function(_target,_message){\n                var _from = _message.from;\n                while(!!_target){\n                    if (_target._$getPath()!=_from){\n                        _doSendMessage(_target,_message);\n                    }\n                    _target = _target._$getParent();\n                }\n            },\n            // broadcast to all target descendants\n            function(_target,_message){\n                var _from = _message.from;\n                _t3._$breadthFirstSearch(\n                    _target,function(_node){\n                        if (_node._$getPath()!=_from){\n                            _doSendMessage(_node,_message);\n                        }\n                    }\n                );\n            }\n        ];\n        return function(_message){\n            var _event = _u._$merge({},_message),\n                _target = _t3._$getNodeByUMI(this.__root,_event.to);\n            _event.path = _target._$getPath();\n           (_fmap[_event.mode]||_fmap[0]).call(this,_target,_event);\n        };\n    })();\n    /**\n     * 发布消息\n     *\n     * 脚本举例\n     * ```javascript\n     *   dispatcher._$publish(\n     *       'onchange',{\n     *           from:'/m/login/',\n     *           data:{action:'delete',value:'xxxxxx'}\n     *       }\n     *   );\n     * ```\n     *\n     * @method   module:util/dispatcher/dispatcher._$$Dispatcher#_$publish\n     * @param    {String} arg0 - 消息类型\n     * @param    {Object} arg0 - 消息相关信息\n     * @property {String} from - 消息来源UMI\n     * @property {Object} data - 消息数据\n     * @return   {Void}\n     */\n    _pro._$publish = function(_type,_message){\n        var _message = _u._$merge({},_message);\n        _message.type = _type||'';\n        this._$dispatchEvent(\n            (_message.from||'')+':'\n            +_message.type,_message\n        );\n    };\n    /**\n     * 订阅消息\n     *\n     * 脚本举例\n     * ```javascript\n     *   dispatcher._$subscribe(\n     *       '/m/login/','onchange',\n     *       function(_event){\n     *           // _event.type\n     *           // _event.from\n     *           // _event.data\n     *       }\n     *   );\n     * ```\n     *\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#_$subscribe\n     * @param  {String}   arg0 - 目标模块的UMI\n     * @param  {String}   arg1 - 消息类型\n     * @param  {Function} arg2 - 消息处理回调\n     * @return {Void}\n     */\n    _pro._$subscribe = function(_umi,_type,_callback){\n        _umi = this.__config.al[_umi]||_umi;\n        this._$addEvent(\n            (_umi||'')+':'+(_type||''),_callback\n        );\n    };\n    /**\n     * 取消订阅消息\n     *\n     * 脚本举例\n     * ```javascript\n     *   dispatcher._$unsubscribe(\n     *       '/m/login/','onchange',\n     *       function(_event){\n     *           // 必须同添加的事件一致\n     *       }\n     *   );\n     * ```\n     *\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#_$unsubscribe\n     * @param  {String}   arg0 - 目标模块的UMI\n     * @param  {String}   arg1 - 消息类型\n     * @param  {Function} arg2 - 消息处理回调\n     * @return {Void}\n     */\n    _pro._$unsubscribe = function(_umi,_type,_callback){\n        _umi = this.__config.al[_umi]||_umi;\n        this._$delEvent(\n            (_umi||'')+':'+(_type||''),_callback\n        );\n    };\n    /**\n     * 隐藏非分组私有模块\n     *\n     * 脚本举例\n     * ```javascript\n     *   // 隐藏私有模块\n     *   dispatcher._$hide('/?/m/a/b/');\n     * ```\n     *\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#_$hide\n     * @param  {String} arg0 - 私有模块地址\n     * @return {Void}\n     */\n    _pro._$hide = function(_umi){\n        var _gid = this.__config.mg[_umi];\n        if (_gid==this.__pvseed){\n            this.__groups[_gid]._$hideUMI(_umi);\n        }\n    };\n    /**\n     * 隐藏私有分组\n     * \n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#_$hideGroup\n     * @param  {String} arg0 - 分组ID\n     * @return {Void}\n     */\n    _pro._$hideGroup = function(_gid){\n        var _group = this.__groups[_gid];\n        if (!!_group){\n            _group._$hide();\n        }\n    };\n    /**\n     * 重定向模块，此接口支持\n     *\n     * * 私有模块重定向\n     * * 可访问模块退出前验证\n     * * 重定向地址带查询参数\n     *\n     * 脚本举例\n     * ```javascript\n     *   // 重定向私有模块\n     *   dispatcher._$redirect('/?/m/a/b?a=aa&b=bb');\n     *\n     *   // 系统存在需退出验证模块时需使用以下业务逻辑接管页面自动调整的逻辑\n     *   _v._$addEvent(document,'click',function(_event){\n     *       var _element = _v._$getElement(_event,\n     *                      function(_node){\n     *                          // filter node here\n     *                          // e.g. _node.tagName=='A'\n     *                      });\n     *       if (!!_element){\n     *           _v._$stopDefault(_event);\n     *           dispatcher._$redirect(_e._$dataset(_element,'href'));\n     *       }\n     *   });\n     *\n     *   // 如果页面带跳转的节点有data-href标识跳转地址的情况可以使用{#_$delegate}处理以上业务逻辑\n     *   // <span data-href=\"#/m/a/?a=aa\">aaaa</span>\n     *   // <a href=\"#/m/a/?a=aa\" data-href=\"#/m/a/?a=aa\">bbbbbb</a>\n     *   dispatcher._$delegate();\n     * ```\n     *\n     * @method   module:util/dispatcher/dispatcher._$$Dispatcher#_$redirect\n     * @param    {String}   arg0     - 模块UMI，可以带查询参数\n     * @param    {Object}   arg1     - 配置信息\n     * @property {Variable} input    - 输入数据\n     * @property {Boolean}  replace  - 是否替换当前历史\n     * @property {Boolean}  force    - 是否强制刷新\n     * @property {Boolean}  ignored  - 是否忽略地址变化前的验证\n     * @property {Boolean}  exitable - 是否可强行退出前面的模块\n     * @return   {Void}\n     */\n    _pro._$redirect = function(_url,_options){\n        _options = _options||_o;\n        var _umi = _t3._$path2umi(_url),\n            _location = location.parse(_url);\n        this.__dtmp[_location.path] = _options.input;\n        if (_t3._$isUMIPrivate(_umi)){\n            // dispatch private module\n            this.__onURLChange(_location);\n        }else{\n            // dispatch public module\n            var _group = this.__groups[this.__pbseed],\n                _event = {target:_location,umi:_umi};\n            if (_options.exitable||!!_group._$exitable(_event)){\n                if (location.same(_url)&&!!_options.force){\n                    this.__onURLChange(_location);\n                }else{\n                    location.ignored = !!_options.ignored;\n                    location.redirect(_url,!!_options.replace);\n                }\n            }\n        }\n    };\n    /**\n     * 刷新模块\n     *\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#_$refresh\n     * @param  {String} arg0 - 模块UMI，可以带查询参数\n     * @return {Void}\n     */\n    _pro._$refresh = function(_url){\n        if (!!_url){\n            this._$redirect(_url,{\n                replace:!0,force:!0\n            });\n        }else{\n            this.__groups[this.__pbseed]._$refresh();\n        }\n    };\n    /**\n     * 模块切换跳转委托，\n     * 如果系统存在需退出验证模块时需使用此接口接管页面自动调整的逻辑\n     *\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#_$delegate\n     * @see    module:util/dispatcher/dispatcher._$$Dispatcher#_$redirect\n     * @return {Void}\n     */\n    _pro._$delegate = function(){\n        this.__doInitDomEvent([[\n            document,'click',\n            this.__onClickDelegate._$bind(this)\n        ]]);\n    };\n    /**\n     * 激活调度器，激活之前确保注册完会被调用的模块\n     *\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#_$active\n     * @return {Void}\n     */\n    _pro._$active = function(){\n        location.active();\n    };\n    /**\n     * 模块载入回调\n     *\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#_$loaded\n     * @param  {String} arg0 - 模块UMI\n     * @param  {module:util/dispatcher/module._$$ModuleAbstract} arg1 - 模块构造器\n     * @return {Void}\n     */\n    _pro._$loaded = function(_umi,_module){\n        _umi = this.__config.al[_umi]||_umi;\n        if (!_u._$isArray(_umi)){\n            this._$regist(_umi,_module);\n            this.__groups[this.__config.mg[_umi]]._$loadedUMI(_umi);\n        }else{\n            _u._$forEach(\n                _umi,function(_key){\n                    this._$loaded(_key,_module);\n                },this\n            );\n        }\n    };\n    /**\n     * 获取对应UMI配置的标题信息\n     *\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#_$getTitle\n     * @param  {String} umi - 模块 UMI 标识\n     * @return {String} 模块标题\n     */\n    _pro._$getTitle = function(umi){\n        return this.__getModuleConf(umi,'title');\n    };\n    /**\n     * 获取对应UMI配置的标题信息\n     *\n     * @method module:util/dispatcher/dispatcher._$$Dispatcher#_$getUMIByAlias\n     * @param  {String} alias - 别名\n     * @param  {Number} index - 多个 UMI 指定索引值\n     * @return {String} 别名对应的 UMI 值\n     */\n    _pro._$getUMIByAlias = function(alias, index){\n        var umi = this.__config.al[alias];\n        if (_u._$isArray(umi)){\n            return umi[index||0];\n        }\n        return umi;\n    };\n    /**\n     * 启动调度系统\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/dispatcher/dispatcher'\n     * ],function(_p){\n     *     // 实例化调度器，并在全局设置dispatcher变量供模块使用\n     *     _p._$startup({\n     *         // 设置规则\n     *         rules:{\n     *             title:{\n     *                 '/m/a/':'模块A',\n     *                 '/m/b/':'模块B',\n     *                 '/m/c/':'模块C'\n     *             },\n     *             rewrite:{\n     *                 '404':'/m/c/0/',\n     *                 '/m/c/$1/':/^\\/c\\/([\\d])\\/$/\n     *             }\n     *         },\n     *         // 注册模块\n     *         modules:{\n     *             '/m':'/module/m.html',\n     *             '/m/a/':'/module/m.c.html',\n     *             '/m/b/':'/module/m.c.html',\n     *             '/m/c/':{module:'/module/m.c.html',clazz:'g-mdl-c'}\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/dispatcher/dispatcher._$startup\n     * @param    {Object} arg0 - 配置信息，其他配置同调度器实例化配置\n     * @property {String} tid  - 模版ID，默认template-box\n     * @return   {module:util/dispatcher/dispatcher._$$Dispatcher} 调度器实例\n     */\n    _p._$startup = function(_options){\n        if (!!window.dispatcher){\n            console.error('dispatcher is already startup');\n            return;\n        }\n        window.dispatcher =\n            _p._$$Dispatcher.\n            _$getInstance(_options);\n        _t7._$dumpModules();\n        _t1._$parseTemplate(\n            (_options||_o).tid||'template-box',\n            location.config\n        );\n        _v._$addEvent(\n            document,'templateready',function(){\n                window.setTimeout(\n                    dispatcher._$active._$bind(dispatcher),0\n                );\n            }\n        );\n        return window.dispatcher;\n    };\n\n    if (CMPT){\n        NEJ.P('nej.e')._$startup = _p._$startup;\n        NEJ.P('nej.ut')._$$Dispatcher = _p._$$Dispatcher;\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/dispatcher/dsp/group.js",
    "content": "﻿/*\n * ------------------------------------------\n * 模块分组管理器实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/dispatcher/dsp/group */\nNEJ.define([\n    'base/util',\n    'base/klass',\n    'base/constant',\n    'base/element',\n    'util/ajax/tag',\n    'util/event',\n    'util/template/tpl',\n    './util.js'\n],function(_u,_k,_g,_e,_j,_t0,_t1,_t2,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 模块分组管理器\n     * \n     * @class   module:util/dispatcher/dsp/group._$$GroupManager\n     * @extends module:util/event._$$EventTarget\n     * \n     * @param    {Object} config - 可选配置参数\n     * @property {module:util/dispatcher/dsp/node._$$Node} root - 树根节点\n     * @property {module:util/dispatcher/dispatcher._$$Dispatcher} dispatcher - 调度器\n     */\n    _p._$$GroupManager = _k._$klass();\n    _pro = _p._$$GroupManager._$extend(_t0._$$EventTarget);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method   module:util/dispatcher/dsp/group._$$GroupManager#__reset\n     * @param    {Object} arg0 - 可选配置参数\n     * @return   {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__root = _options.root;\n        this.__dispatcher = _options.dispatcher;\n        this.__mpool = {}; // umi in this group\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/dispatcher/dsp/group._$$GroupManager#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__root;\n        delete this.__mpool;\n        delete this.__dispatcher;\n    };\n    /**\n     * 判断父节点是否被阻止行为\n     * \n     * @protected\n     * @method module:util/dispatcher/dsp/group._$$GroupManager#__isStopped\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg0 - 节点\n     * @return {Boolean} 是否被阻止\n     */\n    _pro.__isStopped = function(_node){\n        if (!_t2._$isNode(_node)) return !1;\n        return !!_node._$getData().stopped||\n               this.__isStopped(_node._$getParent());\n    };\n    /**\n     * 清理阻止标记\n     * \n     * @protected\n     * @method module:util/dispatcher/dsp/group._$$GroupManager#__doClearStopped\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg0 - 节点\n     * @return {Void}\n     */\n    _pro.__doClearStopped = function(_node){\n        if (!_t2._$isNode(_node)) return;\n        delete _node._$getData().stopped;\n        this.__doClearStopped(_node._$getParent());\n    };\n    /**\n     * 隐藏模块\n     * \n     * @protected\n     * @method module:util/dispatcher/dsp/group._$$GroupManager#__doModuleHide\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg0 - 起始节点（包含）\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg1 - 结束节点（不包含）\n     * @return {Void}\n     */\n    _pro.__doModuleHide = function(_from,_to){\n        this.__doModuleCheck('onhide',_from,_to);\n    };\n    /**\n     * 模块显示并检测\n     * \n     * @protected\n     * @method module:util/dispatcher/dsp/group._$$GroupManager#__doModuleShow\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg0 - 起始节点（包含）\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg1 - 结束节点（不包含）\n     * @return {Void}\n     */\n    _pro.__doModuleShow = function(_from,_to){\n        this.__doModuleCheck('onshow',_from,_to);\n        this.__doModuleAction(_from);\n    };\n    /**\n     * 刷新模块\n     * \n     * @protected\n     * @method module:util/dispatcher/dsp/group._$$GroupManager#__doModuleRefresh\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg0 - 节点对象\n     * @return {Void}\n     */\n    _pro.__doModuleRefresh = function(_node){\n        this.__doModuleCheck('onrefresh',_node);\n        this.__doModuleAction(_node);\n    };\n    /**\n     * 标记操作\n     * \n     * @protected\n     * @method module:util/dispatcher/dsp/group._$$GroupManager#__doModuleCheck\n     * @param  {String}  arg0 - 调度类型\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg1 - 起始节点（包含）\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg2 - 结束节点（不包含）\n     * @return {Void}\n     */\n    _pro.__doModuleCheck = function(_type,_from,_to){\n        if (_from==_to||!_t2._$isNode(_from)){\n            return;\n        }\n        // dispatch first if hide module\n        if (_type=='onhide'){\n            this.__doModuleDispatch(_from,_type);\n        }\n        this.__doModuleCheck(\n            _type,_from._$getParent(),_to\n        );\n        if (_type!='onhide'){\n            this.__doModuleDispatch(_from,_type);\n        }\n    };\n    /**\n     * 执行模块行为\n     * \n     * @protected\n     * @method module:util/dispatcher/dsp/group._$$GroupManager#__doModuleAction\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg0 - 节点对象\n     * @return {Boolean} 节点行为是否执行完成\n     */\n    _pro.__doModuleAction = function(_node){\n        if (!_t2._$isNode(_node)){\n            return !0;\n        }\n        var _data = _node._$getData(),\n            _action = _data.action,\n            _module = _data.module;\n        // check parent dispatched\n        // check module loading\n        if (!this.__doModuleAction(_node._$getParent())||\n           (!!_action&&_u._$isString(_module))){\n            return !1;\n        }\n        // dispatch action\n        if (!!_module&&\n            !!_module._$allocate&&\n           (!!_action&&_action!='onhide')){\n            // check node stopped\n            if (this.__isStopped(_node)) return;\n            var _options = {\n                umi:_node._$getPath(),\n                config:_data.config,\n                composite:_data.composite,\n                dispatcher:this.__dispatcher\n            };\n            _module = _module._$allocate(_options);\n            if (_t2._$isModule(_module)){\n                _data.module = _module;\n                this.__doModuleDispatch(_node,'onshow');\n            }else{\n                delete _data.module;\n            }\n        }\n        delete _data.action;\n        \n        return !0;\n    };\n    /**\n     * 调度模块事件，如果模块已经载入则调度相应操作，如果模块未载入则先载入模块\n     * \n     * @protected\n     * @method module:util/dispatcher/dsp/group._$$GroupManager#__doModuleDispatch\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg0 - 节点对象\n     * @param  {String}  arg1 - 事件名称 onshow/onhide/onrefresh\n     * @return {Void}\n     */\n    _pro.__doModuleDispatch = (function(){\n        // get nearest parent export data\n        var _getParentExport = function(_node){\n            var _module;\n            _node = _node._$getParent();\n            while(!!_node){\n                _module = _node._$getData().module;\n                if (_t2._$isModule(_module)){\n                    return _module._$getExportData();\n                }\n                _node = _node._$getParent();\n            }\n            return null;\n        };\n        // parse module url\n        // config - ver,root,mode\n        var _doParseModuleURL = function (module, config) {\n            var ret = {\n                url: (config.root||'')+module,\n                version: (config.ver||_o)[module]\n            };\n            // convert xxx.html to xxx_ver.html\n            if (!!config.mode&&!!ret.version){\n                ret.url = ret.url.replace(\n                    /(\\.[^.\\/]*?)$/,\n                    '_'+ret.version+'$1'\n                );\n                ret.version = null;\n            }\n            return ret;\n        };\n        return function(_node,_name){\n            if (!_t2._$isNode(_node)){\n                return;\n            }\n            // format data\n            var _data = _node._$getData(),\n                _module = _data.module,\n                _nothide = _name!='onhide';\n            if (_t2._$isModule(_module)){\n                // check node stopped\n                if (_nothide&&this.__isStopped(_node)){\n                    return;\n                }\n                // check event\n                var _event = !this.__source ? _data.event\n                             :this.__source._$getData().event;\n                if (!!_event){\n                    _event.umi = _node._$getPath();\n                    _event.data = _getParentExport(_node);\n                }\n                // check event name\n                // order must be onhide->onshow->onrefresh\n                // onshow must after onhide\n                var _xname = _data.xname||'onhide';\n                if (_name=='onshow'&&_xname!='onhide'){\n                    _name = 'onrefresh';\n                }\n                // onrefresh must after onshow\n                if (_name=='onrefresh'&&_xname=='onhide'){\n                    _name = 'onshow';\n                }\n                _data.xname = _name;\n                // do dispatch event\n                _module._$dispatchEvent(_name,_event||{});\n                // position to element\n                if (_nothide&&\n                    !!_event&&\n                    !!_event.pos&&\n                    _event.umi==_event.target){\n                    _e._$scrollTo(_event.pos);\n                }\n                // check stopped flag\n                if (_nothide&&!!_event){\n                    _data.stopped = _event.stopped;\n                    delete _event.stopped;\n                }\n            }else if(!!_module){\n                _data.action = _name;\n                if (_name=='onshow'&&_u._$isString(_module)){\n                    // check module template inline\n                    var _element = _e._$get('umi://'+_module);\n                    if (!!_element){\n                        _t1._$parseTemplate(_element);\n                    }else{\n                        // support xxx_23423423.html mode\n                        var _config = location.config||_o,\n                            ret = _doParseModuleURL(\n                                _module, _config\n                            );\n                        _j._$loadTemplate(ret.url,{\n                            version:ret.version,\n                            onload:_t1._$parseTemplate\n                        });\n                    }\n                }\n            }\n        };\n    })();\n    /**\n     * 判断UMI是否属于该分组管理器\n     * \n     * @method module:util/dispatcher/dsp/group._$$GroupManager#_$hasUMI\n     * @param  {String}  arg0 - 模块UMI\n     * @return {Boolean} 是否属于该分组管理器\n     */\n    _pro._$hasUMI = function(_umi){\n        return !!this.__mpool[_umi];\n    };\n    /**\n     * 将UMI加入分组管理器中\n     * \n     * @method module:util/dispatcher/dsp/group._$$GroupManager#_$addUMI\n     * @param  {String} arg0 - 模块UMI\n     * @return {Void}\n     */\n    _pro._$addUMI = function(_umi){\n        this.__mpool[_umi] = !0;\n    };\n    /**\n     * 删除分组管理器中的UMI\n     * \n     * @method module:util/dispatcher/dsp/group._$$GroupManager#_$delUMI\n     * @param  {Object} arg0 - 模块UMI\n     * @return {Void}\n     */\n    _pro._$delUMI = function(_umi){\n        delete this.__mpool[_umi];\n    };\n    /**\n     * 指定UMI的模块载入完成\n     * \n     * @method module:util/dispatcher/dsp/group._$$GroupManager#_$loadedUMI\n     * @param  {String} arg0 - 模块UMI\n     * @return {Void}\n     */\n    _pro._$loadedUMI = function(_umi){\n        if (this._$hasUMI(_umi)){\n            this.__doModuleAction(\n                _t2._$getNodeByUMI(this.__root,_umi)\n            );\n        }\n    };\n    /**\n     * 调度到指定UMI的模块\n     * \n     * @method module:util/dispatcher/dsp/group._$$GroupManager#_$dispatchUMI\n     * @param  {String} arg0 - 模块UMI\n     * @return {Void}\n     */\n    _pro._$dispatchUMI = function(_umi){\n        if (this._$hasUMI(_umi)){\n            var _node = _t2._$getNodeByUMI(this.__root,_umi);\n            this.__doClearStopped(_node);\n            this.__doModuleShow(_node);\n        }\n    };\n    /**\n     * 隐藏指定UMI的模块\n     * \n     * @method module:util/dispatcher/dsp/group._$$GroupManager#_$hideUMI\n     * @param  {String} arg0 - 模块UMI\n     * @return {Void}\n     */\n    _pro._$hideUMI = function(_umi){\n        if (this._$hasUMI(_umi)){\n            this.__doModuleHide(\n                _t2._$getNodeByUMI(this.__root,_umi)\n            );\n        }\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/dispatcher/dsp/node.js",
    "content": "/*\n * ------------------------------------------\n * 树节点对象实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/dispatcher/dsp/node */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    'util/event'\n],function(NEJ,_k,_u,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 树节点对象\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/dispatcher/dsp/node'\n     * ],function(_p){\n     *     //      ___\n     *     //     |_/_|       <-- 节点名称为\"/\"的节点\n     *     //     /   \\\n     *     //   _/_   _\\_ \n     *     //  |_a_| |_b_|    <-- 节点名称为\"b\"的节点\n     * \n     *     // 分配一个名称为“/”的节点\n     *     var _root = _p._$$Node._$allocate();\n     * \n     *     // 分配一个名称为“a”的节点，并指定父节点为_root\n     *     var _node = _p._$$Node._$allocate({\n     *         parent:_root,\n     *         name:'a'\n     *     });\n     * \n     *     // 分配一个名称为“b”的节点，手动设置父节点\n     *     var _node = _$$Node._$allocate({\n     *         name:'b'\n     *     });\n     *     _node._$setParent(_root);\n     * \n     *     // 回收树，同时回收节点的所有子孙节点\n     *     _root = _root._$recycle();\n     * });\n     * ```\n     * \n     * @class    module:util/dispatcher/dsp/node._$$Node\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object}  config - 可选配置参数\n     * @property {_$$Node} parent - 父节点\n     * @property {String}  name   - 节点名称，默认为\"/\"\n     * @property {Object}  data   - 节点缓存的数据信息\n     */\n    _p._$$Node = _k._$klass();\n    _pro = _p._$$Node._$extend(_t._$$EventTarget);\n    /**\n     * 控件初始化\n     * \n     * @protected\n     * @method module:util/dispatcher/dsp/node._$$Node#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__super();\n        this.__children = [];\n    };\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/dispatcher/dsp/node._$$Node#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this._$setParent(_options.parent);\n        this.__name = _options.name||'/';\n        this.__data = _options.data||{};\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/dispatcher/dsp/node._$$Node#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = (function(){\n        var _doRecycle = function(_node,_index,_list){\n            _list.splice(_index,1);\n            _node._$recycle();\n        };\n        return function(){\n            this.__super();\n            delete this.__data;\n            _u._$reverseEach(\n                this.__children,\n                _doRecycle\n            );\n            this._$setParent(null);\n        };\n    })();\n    /**\n     * 是否节点实例\n     * \n     * @protected\n     * @method module:util/dispatcher/dsp/node._$$Node#__isNode\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg0 - 节点\n     * @return {Boolean} 是否节点实例\n     */\n    _pro.__isNode = function(_node){\n        return _node instanceof this.constructor;\n    };\n    /**\n     * 是否有子节点\n     * \n     * @protected\n     * @method module:util/dispatcher/dsp/node._$$Node#__hasChild\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg0 - 子节点\n     * @return {Boolean} 是否有子节点\n     */\n    _pro.__hasChild = function(_child){\n        return _u._$indexOf(this.__children,_child)>=0;\n    };\n    /**\n     * 取节点名称\n     * \n     * @method module:util/dispatcher/dsp/node._$$Node#_$getName\n     * @return {String} 节点名称\n     */\n    _pro._$getName = function(){\n        return this.__name;\n    };\n    /**\n     * 取节点保存的信息\n     * \n     * @method module:util/dispatcher/dsp/node._$$Node#_$getData\n     * @return {Object} 数据信息\n     */\n    _pro._$getData = function(){\n        return this.__data;\n    };\n    /**\n     * 取当前节点路径\n     * \n     * @method module:util/dispatcher/dsp/node._$$Node#_$getPath\n     * @return {String} 路径\n     */\n    _pro._$getPath = function(){\n        var _parent = this._$getParent(),\n            _name = this._$getName();\n        if (!_parent) return _name;\n        var _pname = _parent._$getName();\n        if (_pname!='/'&&_name!='/')\n            _name = '/'+_name;\n        return _parent._$getPath()+_name;\n    };\n    /**\n     * 取父节点\n     * \n     * @method module:util/dispatcher/dsp/node._$$Node#_$getParent\n     * @return {_$$Node} 父节点\n     */\n    _pro._$getParent = function(){\n        return this.__parent;\n    };\n    /**\n     * 取子节点列表\n     * \n     * @method module:util/dispatcher/dsp/node._$$Node#_$getChildren\n     * @return {Array} 子节点列表\n     */\n    _pro._$getChildren = function(){\n        return this.__children;\n    };\n    /**\n     * 取指定名称的子节点\n     * \n     * @method module:util/dispatcher/dsp/node._$$Node#_$getChildByName\n     * @param  {String} arg0 - 名称\n     * @return {module:util/dispatcher/dsp/node._$$Node} 子节点\n     */\n    _pro._$getChildByName = function(_name){\n        var _index = _u._$indexOf(\n            this.__children,function(_node){\n                return _name==_node._$getName();\n            }\n        );\n        return this.__children[_index]||null;\n    };\n    /**\n     * 设置父节点\n     * \n     * @method module:util/dispatcher/dsp/node._$$Node#_$setParent\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg0 - 父节点\n     * @return {Void}\n     */\n    _pro._$setParent = function(_parent){\n        _parent = this.__isNode(_parent)?_parent:null;\n        if (_parent==this.__parent) return;\n        !!_parent ? _parent._$appendChild(this)\n                  : this.__parent._$removeChild(this);\n        this.__parent = _parent;\n    };\n    /**\n     * 添加子节点\n     * \n     * @method module:util/dispatcher/dsp/node._$$Node#_$appendChild\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg0 - 子节点\n     * @return {Void}\n     */\n    _pro._$appendChild = function(_child){\n        _child = this.__isNode(_child)?_child:null;\n        if (!_child||this.__hasChild(_child)) return;\n        this.__children.push(_child);\n        _child._$setParent(this);\n    };\n    /**\n     * 删除子节点\n     * \n     * @method module:util/dispatcher/dsp/node._$$Node#_$removeChild\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg0 - 子节点\n     * @return {module:util/dispatcher/dsp/node._$$Node} 删除的节点\n     */\n    _pro._$removeChild = function(_child){\n        _child = this.__isNode(_child)?_child:null;\n        var _index = _u._$indexOf(this.__children,_child);\n        if (_index>=0){\n            this.__children.splice(_index,1);\n            _child._$setParent(null);\n        }\n        return _child;\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/dispatcher/dsp/single.js",
    "content": "/*\n * ------------------------------------------\n * 模块分组管理器实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/dispatcher/dsp/single */\nNEJ.define([\n    'base/klass',\n    'base/element',\n    './util.js',\n    './group.js'\n],function(_k,_e,_t0,_t1,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 模块分组管理器\n     * \n     * @class   module:util/dispatcher/dsp/single._$$GroupManagerSingle\n     * @extends module:util/dispatcher/dsp/group._$$GroupManager\n     * \n     * @param    {Object}  config  - 可选配置参数\n     * @property {Boolean} classed - 是否需要切换样式\n     */\n    _p._$$GroupManagerSingle = _k._$klass();\n    _pro = _p._$$GroupManagerSingle._$extend(_t1._$$GroupManager);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/dispatcher/dsp/single._$$GroupManagerSingle#__reset\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__classed = !!_options.classed;\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/dispatcher/dsp/single._$$GroupManagerSingle#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__cmroot;\n        delete this.__source;\n    };\n    /**\n     * 判断当前模块是否可以退出\n     * \n     * @method module:util/dispatcher/dsp/single._$$GroupManagerSingle#_$exitable\n     * @param  {Object}  arg0 - 目标信息\n     * @return {Boolean} 是否允许退出当前模块\n     */\n    _pro._$exitable = function(_event){\n        if (!this.__source){\n            return !0;\n        }\n        var _module = this.__source._$getData().module;\n        // sure module has loaded\n        if (_t0._$isModule(_module)){\n            _module._$dispatchEvent('onbeforehide',_event);\n        }\n        return !_event.stopped;\n    };\n    /**\n     * 刷新当前模块\n     * \n     * @method module:util/dispatcher/dsp/single._$$GroupManagerSingle#_$refresh\n     * @return {Void}\n     */\n    _pro._$refresh = function(){\n        if (!this.__source) return;\n        // keep asynchronous for finishing last process\n        window.setTimeout(\n            this._$dispatchUMI._$bind(\n                this,this.__source._$getPath()\n            ),0\n        );\n    };\n    /**\n     * 调度到指定UMI的模块,大致调度策略为:\n     * \n     * 1. 计算原始节点与目标节点的公共节点\n     * 2. 依次刷新根节点到公共节点之间的节点上注册的模块\n     * 3. 依次隐藏原始节点到公共节点之间的节点上注册的模块\n     * 4. 依次显示公共节点到目标节点之间的节点上注册的模块\n     *   \n     * 执行过程中遇到任何需要动态载入的模块均自动载入,\n     * 子节点执行操作之前必须确保父节点已执行完相应操作\n     * \n     * 以下两种情况忽略本次调度逻辑:\n     * \n     * * 需要调度的UMI非本组管理器的UMI\n     * * 需要调度的UMI上没有注册模块\n     * \n     * @method module:util/dispatcher/dsp/single._$$GroupManagerSingle#_$dispatchUMI\n     * @param  {String} arg0 - 模块UMI\n     * @return {Void}\n     */\n    _pro._$dispatchUMI = function(_umi){\n        if (!this._$hasUMI(_umi)) return;\n        var _target = _t0._$getNodeByUMI(this.__root,_umi),\n            _data = _target._$getData();\n        // no module registed in target\n        if (!_data.module) return;\n        // update event information\n        var _source = this.__source,\n            _event  = _data.event,\n            _odata  = _o;\n        this.__source = _target;\n        this.__doClearStopped(_target);\n        if (!!_source){\n            _odata = _source._$getData().event;\n            _event.referer = _odata.href||'';\n        }\n        // source==target do refresh\n        if (_source==_target){\n            this.__doModuleRefresh(this.__source);\n            return;\n        }\n        // hide source\n        this.__cmroot = _t0._$getCommonRoot(\n            this.__root,_source,_target\n        );\n        if (_source!=null){\n            // hide source -> common root\n            if (_source!=this.__cmroot){\n                if (this.__classed){\n                    _e._$delClassName(\n                        document.body,\n                        _odata.clazz\n                    );\n                }\n                this.__doModuleHide(\n                    _source,this.__cmroot\n                );\n            }\n            // refresh common root -> root\n            this.__doModuleRefresh(this.__cmroot);\n        }else{\n            // show common root -> root\n            this.__doModuleShow(this.__cmroot);\n        }\n        // show target\n        if (_target!=this.__cmroot){\n            if (this.__classed){\n                _e._$addClassName(\n                    document.body,_event.clazz\n                );\n            }\n            // show target -> common root\n            this.__doModuleShow(_target,this.__cmroot);\n        }\n    };\n    /**\n     * 指定UMI的模块载入完成\n     * \n     * @method module:util/dispatcher/dsp/single._$$GroupManagerSingle#_$loadedUMI\n     * @param  {String} arg0 - 模块UMI\n     * @return {Void}\n     */\n    _pro._$loadedUMI = function(_umi){\n        if (this._$hasUMI(_umi)){\n            this.__doModuleAction(this.__source);\n        }\n    };\n    /**\n     * 隐藏当前分组\n     * \n     * @method module:util/dispatcher/dsp/single._$$GroupManagerSingle#_$hide\n     * @return {Void}\n     */\n    _pro._$hide = function(){\n        if (!this.__source){\n            return;\n        }\n        this._$hideUMI(\n            this.__source._$getPath()\n        );\n        delete this.__cmroot;\n        delete this.__source;\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/dispatcher/dsp/util.js",
    "content": "/*\n * ------------------------------------------\n * 调度器辅助接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/dispatcher/dsp/util */\nNEJ.define([\n    'base/util',\n    './node.js',\n    '../module.js'\n],function(_u,_t0,_t1,_p,_o,_f,_r){\n    /*\n     * 解析UMI对应的节点\n     * @param  {_$$Node}  根节点\n     * @param  {String}   UMI值\n     * @param  {Function} 解析过程处理函数\n     * @return {_$$Node}  对应节点\n     */\n    var _doParseUMI = function(_root,_umi,_hanlder){\n        var _node = _root,\n            _hanlder = _hanlder||_f;\n        if (_umi!='/'){\n            _u._$forEach(\n                _umi.split('/'),function(_name){\n                    var _result = _hanlder(_node,_name);\n                    if (!_result) \n                        return !0;\n                    _node = _result;\n                }\n            );\n        }\n        return _node;\n    };\n    /**\n     * 根据UMI取对应的节点\n     * \n     * @method module:util/dispatcher/dsp/util._$getNodeByUMI\n     * @param  {module:util/dispatcher/dsp/node._$Node} arg0 - 根节点\n     * @param  {String} arg1 - UMI值\n     * @return {module:util/dispatcher/dsp/node._$Node} UMI对应的节点\n     */\n    _p._$getNodeByUMI = (function(){\n        var _doSearch = function(_parent,_name){\n            var _name = _name||'/',\n                _pname = _parent._$getName();\n            if (_pname=='/'&&_name=='/')\n                return _parent;\n            return _parent._$getChildByName(_name);\n        };\n        return function(_root,_umi){\n            return _doParseUMI(_root,_umi,_doSearch);\n        };\n    })();\n    /**\n     * 根据UMI追加对应的节点\n     * \n     * @method module:util/dispatcher/dsp/util._$appendNodeByUMI\n     * @param  {module:util/dispatcher/dsp/node._$Node} arg0 - 根节点\n     * @param  {String} arg1 - UMI值\n     * @return {module:util/dispatcher/dsp/node._$Node} UMI对应的节点\n     */\n    _p._$appendNodeByUMI = (function(){\n        // build tree\n        var _doBuild = function(_parent,_name){\n            var _pname = _parent._$getName();\n            // root not add slash child\n            if (!_name&&_pname=='/'){\n                return _parent;\n            }\n            var _node = null;\n            // check slash child first\n            if (_pname!='/'){\n                _node = _parent._$getChildByName('/');\n                if (!_node){\n                    _node = _t0._$$Node._$allocate();\n                    _parent._$appendChild(_node);\n                }\n            }\n            // check non-slash child\n            if (!!_name){\n                _node = _parent._$getChildByName(_name);\n                if (!_node){\n                    _node = _t0._$$Node._$allocate({name:_name});\n                    _parent._$appendChild(_node);\n                }\n            }\n            return _node;\n        };\n        return function(_root,_umi){\n            return _doParseUMI(_root,_umi,_doBuild);\n        };\n    })();\n    /**\n     * 取两个节点的公共\n     * \n     * @method module:util/dispatcher/dsp/util._$getCommonRoot\n     * @param  {module:util/dispatcher/dsp/node._$Node} arg0 - 匹配节点\n     * @param  {module:util/dispatcher/dsp/node._$Node} arg1 - 匹配节点\n     * @return {module:util/dispatcher/dsp/node._$Node}        公共节点\n     */\n    _p._$getCommonRoot = function(_root,_source,_target){\n        if (!_source||!_target) return _root;\n        var _source = _source._$getPath().split('/'),\n            _target = _target._$getPath().split('/'),\n            _difidx = _u._$forIn(\n                _source,function(_value,_index){\n                    if (_value!=_target[_index]){\n                        return !0;\n                    }\n                }\n            )||1,\n            _umi = _source.splice(0,_difidx).join('/')||'/';\n        return _p._$getNodeByUMI(_root,_umi);\n    };\n    /**\n     * 广度优先搜索\n     * \n     * @method module:util/dispatcher/dsp/util._$breadthFirstSearch\n     * @param  {module:util/dispatcher/dsp/node._$Node} arg0 - 起始节点\n     * @param  {Function} arg1 - 搜索过程处理函数\n     * @return {Void}\n     */\n    _p._$breadthFirstSearch = function(_root,_handler){\n        var _arr = [_root],\n            _node = _arr.shift(),\n            _handler = _handler||_f;\n        while(!!_node){\n            _arr.push.apply(\n                _arr,_node._$getChildren()\n            );\n            _handler(_node);\n            _node = _arr.shift();\n        }\n    };\n    /**\n     * 判断是否节点实例\n     * \n     * @method module:util/dispatcher/dsp/util._$isNode\n     * @param  {module:util/dispatcher/dsp/node._$$Node} arg0 - 节点\n     * @return {Boolean} 是否节点实例\n     */\n    _p._$isNode = function(_node){\n        return _node instanceof _t0._$$Node;\n    };\n    /**\n     * 判断是否模块实例\n     * \n     * @method module:util/dispatcher/dsp/util._$isModule\n     * @param  {module:util/dispatcher/module._$$ModuleAbstract} arg0 - 模块实例\n     * @return {Boolean}          是否模块实例\n     */\n    _p._$isModule = function(_module){\n        return _module instanceof _t1._$$ModuleAbstract;\n    };\n    /**\n     * 判断给定UMI是否代表私有模块\n     * \n     * @method module:util/dispatcher/dsp/util._$isUMIPrivate\n     * @param  {String}  arg0 - UMI值\n     * @return {Boolean}        是否私有模块\n     */\n    _p._$isUMIPrivate = (function(){\n        var _reg = /^\\/?\\?(?=\\/|$)/;\n        return function(_umi){\n            return _reg.test(_umi||'');\n        };\n    })();\n    /**\n     * 路径转UMI\n     * \n     * 转换逻辑\n     * \n     * 1. 路径按照\"?\"或者\"#\"分割\n     * 2. 识别私有模块，条件：第一个元素为\"/\"同时第二个元素以\"?\"开始\n     * 3. 非私有模块返回第一个元素，私有模块返回用\"?\"合并的第一和第二个元素\n     * \n     * 转换举例\n     * ```\n     * /a/b              ->   /a/b\n     * /a/b?a=aa         ->   /a/b\n     * /a/b#a=aa         ->   /a/b\n     * /a/b?a=aa#b=bb    ->   /a/b\n     * /a/b#a=aa?b=bb    ->   /a/b\n     * /a/b?/a/b         ->   /a/b\n     * /a/b#/a/b         ->   /a/b\n     * /?/a/b            ->   /?/a/b\n     * /?/a/b?a=aa       ->   /?/a/b\n     * /?/a/b#a=aa       ->   /?/a/b\n     * /?/a/b?a=aa#b=bb  ->   /?/a/b\n     * /?/a/b#a=aa?b=bb  ->   /?/a/b\n     * /?a=aa            ->   /\n     * /#a=aa            ->   /\n     * ```\n     * \n     * @method module:util/dispatcher/dsp/util._$path2umi\n     * \n     * @param  {String} arg0 - 路径，可带查询参数\n     * @return {String}        模块UMI\n     */\n    _p._$path2umi = (function(){\n        var _reg = /[\\?#]/;\n        return function(_url){\n            var _arr = (_url||'').trim().split(_reg),\n                _prv = _arr[0]=='/'&&(_arr[1]||'').indexOf('/')==0;\n            return _arr[0]+(_prv?('?'+_arr[1]):'');\n        };\n    })();\n    \n    return _p;    \n});\n"
  },
  {
    "path": "src/util/dispatcher/module.base.js",
    "content": "// link to util/dispatcher/module for compatible\n// use util/dispatcher/module for new project\nNEJ.define(['./module.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/dispatcher/module.js",
    "content": "/*\n * ------------------------------------------\n * 项目模块基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/dispatcher/module */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/util',\n    'util/event',\n    './dispatcher.js'\n],function(NEJ,_k,_e,_u,_t0,_t1,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 项目模块基类对象\n     * \n     * @class    module:util/dispatcher/module._$$ModuleAbstract\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object} config    - 可选配置参数\n     * @property {String} umi       - 当前模块的统一模块标识符\n     * @property {Object} composite - 组合模块配置信息\n     * @property {module:util/dispatcher/dispatcher._$$Dispatcher} dispatcher - 调度器实例\n     */\n    _p._$$ModuleAbstract = _k._$klass();\n    _pro = _p._$$ModuleAbstract._$extend(_t0._$$EventTarget);\n    /**\n     * 控件初始化\n     * \n     * @protected\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__init\n     * @return {Void}\n     */\n    _pro.__init = function(_options){\n        this.__super(_options);\n        this.__export = {};\n        this.__doBuild(_options.config);\n    };\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__umi = _options.umi||'';\n        this.__dispatcher = _options.dispatcher;\n        this.__composites = _options.composite||_o;\n        // void rewrite\n        this._$batEvent({\n            onshow:this.__onShow._$bind(this),\n            onhide:this.__onHide._$bind(this),\n            onrefresh:this.__onRefresh._$bind(this),\n            onmessage:this.__onMessage._$bind(this),\n            onbeforehide:this.__onBeforeHide._$bind(this)\n        });\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        this.__export = {};\n        delete this.__umi;\n        delete this.__composites;\n        delete this.__dispatcher;\n    };\n    /**\n     * 阻止事件\n     * \n     * @protected\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__stop\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__stop = function(_event){\n        if (!!_event){\n            _event.stopped = !0;\n        }\n    };\n    /**\n     * 构建模块，子类实现具体业务逻辑\n     * \n     * @abstract\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__doBuild\n     * @return {Void}\n     */\n    _pro.__doBuild = _f;\n    /**\n     * 模块退出前触发事件，通过阻止输入的事件做退出验证，子类实现具体逻辑\n     * \n     * @abstract\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__onBeforeHide\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onBeforeHide = _f;\n    /**\n     * 清除所有组合控件，除了调度器控件\n     * \n     * @protected\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__doClearComponentExDsp\n     * @return {Void}\n     */\n    _pro.__doClearComponentExDsp = (function(){\n        var _doCheck = function(_component){\n            return !!_t1._$$Dispatcher&&\n                    (_component instanceof _t1._$$Dispatcher);\n        };\n        return function(){\n            this.__doClearComponent(_doCheck);\n        };\n    })();\n    /**\n     * 接受到消息触发事件，子类实现具体逻辑\n     * \n     * @abstract\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__onMessage\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onMessage = _f;\n    /**\n     * 向目标模块发送消息\n     * \n     * @protected\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__doSendMessage\n     * @param  {String}   arg0 - 目标模块UMI\n     * @param  {Variable} arg1 - 消息内容\n     * @param  {Number}   arg2 - 消息模式\n     * @return {Void}\n     */\n    _pro.__doSendMessage = function(_to,_message,_mode){\n        this.__dispatcher._$message({\n            to:_to,\n            mode:_mode||0,\n            data:_message,\n            from:this.__umi\n        });\n    };\n    /**\n     * 发布消息\n     * \n     * @protected\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__doPublishMessage\n     * @param  {String} arg0 - 消息类型\n     * @param  {Object} arg1 - 消息信息\n     * @return {Void}\n     */\n    _pro.__doPublishMessage = function(_type,_data){\n        this.__dispatcher._$publish(\n            _type,{\n                from:this.__umi,\n                data:_data\n            }\n        );\n    };\n    /**\n     * 订阅消息\n     * \n     * @protected\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__doSubscribeMessage\n     * @param  {String}   arg0 - 目标模块的UMI\n     * @param  {String}   arg1 - 消息类型\n     * @param  {Function} arg2 - 消息处理回调\n     * @return {Void}\n     */\n    _pro.__doSubscribeMessage = function(){\n        this.__dispatcher._$subscribe\n            .apply(this.__dispatcher,arguments);\n    };\n    /**\n     * 取模块对外开放的数据信息，依赖此模块的子模块可以访问到此信息\n     * \n     * @method module:util/dispatcher/module._$$ModuleAbstract#_$getExportData\n     * @return {Object} 对外开放的数据信息\n     */\n    _pro._$getExportData = function(){\n        return this.__export;\n    };\n    /**\n     * 解析模块所在容器节点\n     * \n     * @protected\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__doParseParent\n     * @param  {Object} arg0 - 配置信息\n     * @return {Node}          模块所在容器节点\n     */\n    _pro.__doParseParent = function(_options){\n        // try get parent\n        // check input first\n        var _parent;\n        if (!_parent){\n            var _data = _options.input||_o;\n            _parent = _e._$get(_data.parent);\n        }\n        if (!_parent){\n            var _data = _options.data||_o;\n            _parent = _e._$get(_data.parent);\n        }\n        if (!_parent){\n            _parent = _e._$get(_options.parent);\n        }\n        return _parent;\n    };\n    /**\n     * 显示模块触发事件，子类可重写具体逻辑\n     * \n     * @protected\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__onShow\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onShow = function(_options){\n        var _parent = this.__doParseParent(_options);\n        // show and refresh module\n        if (!!_parent&&!!this.__body){\n            _parent.appendChild(this.__body);\n        }\n        this.__doApplyComposite('onshow',_options);\n        this.__onRefresh(_options);\n    };\n    /**\n     * 显示模块触发事件，子类实现具体逻辑\n     * \n     * @protected\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__onRefresh\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onRefresh = function(_options){\n        this.__doApplyComposite('onrefresh',_options);\n    };\n    /**\n     * 隐藏模块触发事件，子类实现具体逻辑\n     * \n     * @protected\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__onHide\n     * @return {Void}\n     */\n    _pro.__onHide = function(){\n        this.__doHideComposite();\n        _e._$removeByEC(this.__body);\n    };\n    /**\n     * 是否忽略模块组合\n     * \n     * @protected\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__isEscapedComposite\n     * @return {Boolean} 是否忽略\n     */\n    _pro.__isEscapedComposite = (function(){\n        var _reg0 = /^onshow|onrefresh|delay$/;\n        return function(_umi){\n            return _reg0.test(_umi);    \n        };\n    })();\n    /**\n     * 动态生成组合模块的输入参数，子类实现具体业务逻辑\n     * \n     * @abstract\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__doGenCompositeParam\n     * @param  {String} arg0 - 模块类别\n     * @param  {Object} arg1 - 输入信息\n     * @return {Object}        参数信息\n     */\n    _pro.__doGenCompositeParam = _f;\n    /**\n     * 应用组合模块\n     * \n     * @protected\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__doApplyComposite\n     * @param  {String} arg0 - 类型，onshow/onrefresh\n     * @param  {Object} arg1 - 事件对象\n     * @return {Void}\n     */\n    _pro.__doApplyComposite = (function(){\n        var _doRedirect = function(_query,_options,_umi,_pid){\n            if (this.__isEscapedComposite(_pid)) return;\n            if (!!_query) _umi += (_umi.indexOf('?')>1?'&':'?')+_query;\n            var _input = this.__doGenCompositeParam(_pid,_options)||{};\n            _input.location = _options;\n            _input.parent = this.__export[_pid];\n            this.__dispatcher._$redirect(_umi,{input:_input});\n        };\n        return function(_type,_options){\n            if (!_options.nodelay){\n                // delay all\n                if (!!this.__composites.delay) return;\n                // check delay\n                var _composite = this.__composites[_type]||_o;\n                if (_composite.delay) return;\n            }\n            // do apply\n            var _query = _u._$object2query(_options.param)||'';\n            if (_type=='onrefresh'){\n                _u._$loop(\n                    this.__composites,\n                    _doRedirect._$bind(this,_query,_options)\n                );\n            }\n            _u._$loop(\n                _composite,_doRedirect.\n                _$bind(this,_query,_options)\n            );\n        };\n    })();\n    /**\n     * 隐藏组合模块\n     * \n     * @protected\n     * @method module:util/dispatcher/module._$$ModuleAbstract#__doHideComposite\n     * @return {Void}\n     */\n    _pro.__doHideComposite = (function(){\n        var _doHide = function(_umi,_pid){\n            if (!this.__isEscapedComposite(_pid)){\n                this.__dispatcher._$hide(_umi);\n            }\n        };\n        return function(){\n            _u._$loop(this.__composites,_doHide,this);\n            _u._$loop(this.__composites.onshow,_doHide,this);\n            _u._$loop(this.__composites.onrefresh,_doHide,this);\n        };\n    })();\n    /**\n     * 注册模块，如果调度器还没有被实例化则先缓存注册内容\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/dispatcher/module'\n     * ],function(_t){\n     *     // 注册别名\n     *     _t._$regist('blog-list',a._$$Module);\n     *\n     *     // 注册UMI\n     *     _t._$regist('/blog/list/',a._$$Module);\n     * });\n     * ```\n     * \n     * @method module:util/dispatcher/module._$regist\n     * @param  {String} arg0 - 模块UMI或者别名\n     * @param  {module:util/dispatcher/module._$$ModuleAbstract} arg1 - 模块构造函数\n     * @return {Void}\n     */\n    _p._$regist = (function(){\n        var _modules;\n        // dump modules for dispatcher startup\n        _p._$dumpModules = function(){\n            if (!_modules) return;\n            _u._$loop(_modules,function(_module,_umi){\n                dispatcher._$loaded(_umi,_module);\n            });\n            _modules = null;\n        };\n        return function(_umi,_module){\n            if (!!window.dispatcher){\n                dispatcher._$loaded.\n                    apply(dispatcher,arguments);\n            }else{\n                if (!_modules){\n                    _modules = {};\n                }\n                _modules[_umi] = _module;\n            }\n        };\n    })();\n    \n    if (CMPT){\n        NEJ.P('nej.e')._$regist = _p._$regist;\n        NEJ.P('nej.ut')._$$Module = _p._$$ModuleAbstract;\n        NEJ.P('nej.ut')._$$AbstractModule = _p._$$ModuleAbstract;\n    }\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/dispatcher/platform/dispatcher.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   \n * ------------------------------------------\n */\nNEJ.define([\n    'base/platform'\n],function(_m,_p,_o,_f,_r){\n    /**\n     * 修正标题\n     * @param  {String} 上次标题\n     * @return {String} 修正后的标题\n     */\n    _p.__doFixTitle = (function(){\n        var _reg = /#.*?$/i;\n        return function(_title){\n            var _odttl = document.title,\n                _nwttl = _odttl.replace(_reg,'');\n            if (_odttl!=_nwttl){\n                _title = _nwttl||_title;\n                document.title = _title;\n            }\n            return document.title;\n        };\n    })();\n    /**\n     * 修正标题被Hash污染问题\n     * @param  {String} 原始标题\n     * @return {Void}\n     */\n    _p.__doFixHashTitle = function(_title){\n        // TODO\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/dispatcher/platform/dispatcher.patch.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   \n * ------------------------------------------\n */\nNEJ.define([\n    './dispatcher.js',\n    'base/platform'\n],function(_h,_m,_p,_o,_f,_r){\n    // TR 2.0 - IE 6\n    // TR 3.0 - IE 7\n    // TR 4.0 - IE 8\n    // TR 5.0 - IE 9\n    // TR 6.0 - IE 10\n    // TR 7.0 - IE 11\n    \n    // for ie11+\n    NEJ.patch('TR>=7.0',['base/util'],function(_u){\n        /**\n         * 修正标题被Hash污染问题\n         * @param  {String} 原始标题\n         * @return {Void}\n         */\n        _h.__doFixHashTitle = function(_title){\n            new MutationObserver(function(_list){\n                _u._$reverseEach(\n                    _list,function(_record){\n                        if (_record.target.tagName=='TITLE'||\n                            _record.type=='characterData'){\n                            _title = _h.__doFixTitle(_title);\n                            return !0;\n                        }\n                    }\n                );\n            }).observe(\n                document,{\n                    subtree:!0,\n                    childList:!0,\n                    characterData:!0\n                }\n            );\n        };\n    });\n    // for ie10-\n    NEJ.patch('TR<7.0',['base/event'],function(_v){\n        /** \n         * 修正标题被Hash污染问题\n         * @param  {String} 原始标题\n         * @return {Void}\n         */\n        _h.__doFixHashTitle = function(_title){\n            _v._$addEvent(\n                document,'propertychange',function(_event){\n                    if (_event.propertyName!='title'){\n                        return;\n                    }\n                    _title = _h.__doFixTitle(_title);\n                }\n            );\n        };\n    });\n    \n    return _h;\n});\n"
  },
  {
    "path": "src/util/dispatcher/regularModule.js",
    "content": "/*\n * ------------------------------------------\n * 项目Regualar模块基类实现文件\n * @author   sensen(hzzhaoyusen@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/dispatcher/regularModule */\nNEJ.define([\n    'base/klass',\n    'base/event',\n    'util/template/tpl',\n    'util/dispatcher/module'\n],function(_k,_v,_t,_m,_p){\n    var _pro;\n    /**\n     * Regular模块基类对象\n     *\n     * @class   {_$$RegularModule}\n     * @extends {_$$ModuleAbstract}\n     */\n    _p._$$RegularModule = _k._$klass();\n    _pro = _p._$$RegularModule._$extend(_m._$$ModuleAbstract);\n    /**\n     * 构建Regular组件\n     *\n     * @protected\n     * @method module:util/dispatcher/regularModule._$$RegularModule#__build\n     * @param  {Object} arg0 - 模块配置信息\n     * @return {Void}\n     */\n    _pro.__build = function(config){\n        this._$innerModule = new this._$$InnerModule().$inject(this.__body);\n        this.__export.parent = this._$innerModule.$refs.view;\n\n        this._$innerModule.__doSendMessage = this.__doSendMessage._$bind(this);\n    }\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:util/dispatcher/regularModule._$$RegularModule#__init\n     * @return {Void}\n     */\n    _pro.__init = function(_options){\n        this.__super(_options);\n        this.__nodeKey = _t._$addNodeTemplate('<div></div>');\n        this.__body = _t._$getNodeTemplate(this.__nodeKey);\n\n        this.__build((_options||{}).config);\n    }\n    /**\n     * 显示模块触发事件，子类可重写具体逻辑\n     *\n     * @protected\n     * @method module:util/dispatcher/regularModule._$$RegularModule#__onShow\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onShow = function(_options){\n        // 如果Regular组件被destroy了，就重新构建\n        if(this._$innerModule._watchers === null)\n            this.__build();\n\n        this.__super(_options);\n        if(this._$innerModule.__onShow){\n            this._$innerModule.data.$param = _options.param;\n            this._$innerModule.data.$params = _options.href.split('?')[1];\n            this._$innerModule.__onShow(_options);\n            this._$innerModule.$update();\n        }\n    }\n    /**\n     * 显示模块触发事件，子类实现具体逻辑\n     *\n     * @protected\n     * @method module:util/dispatcher/regularModule._$$RegularModule#__onRefresh\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onRefresh = function(_options){\n        this.__super(_options);\n        if(this._$innerModule.__onRefresh){\n            this._$innerModule.data.$param = _options.param;\n            this._$innerModule.data.$params = _options.href.split('?')[1];\n            this._$innerModule.__onRefresh(_options);\n            this._$innerModule.$update();\n        }\n    }\n    /**\n     * 接受到消息触发事件，子类实现具体逻辑\n     *\n     * @abstract\n     * @method module:util/dispatcher/regularModule._$$RegularModule#__onMessage\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onMessage = function(_options){\n        this.__super(_options);\n        if(this._$innerModule.__onMessage){\n            this._$innerModule.__onMessage(_options);\n            this._$innerModule.$update();\n        }\n    }\n    /**\n     * 模块退出前触发事件，通过阻止输入的事件做退出验证，子类实现具体逻辑\n     *\n     * @abstract\n     * @method module:util/dispatcher/regularModule._$$RegularModule#__onBeforeHide\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onBeforeHide = function(_options){\n        this.__super(_options);\n        if(this._$innerModule.__onBeforeHide){\n            this._$innerModule.__onBeforeHide(_options);\n            this._$innerModule.$update();\n        }\n    }\n    /**\n     * 隐藏模块触发事件，子类实现具体逻辑\n     *\n     * @protected\n     * @method module:util/dispatcher/regularModule._$$RegularModule#__onHide\n     * @return {Void}\n     */\n    _pro.__onHide = function(){\n        this.__super();\n        if(this._$innerModule.__onHide){\n            this._$innerModule.__onHide();\n            this._$innerModule.$update();\n        }\n    }\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/dispatcher/regularModule._$$RegularModule#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__body = _t._$getNodeTemplate(this.__nodeKey);\n        this._$innerModule.destroy();\n        delete this.__nodeKey;\n        this.__super();\n    };\n\n    /**\n     * 注册RegularModule\n     *\n     * @public\n     * @method module:util/dispatcher/regularModule._$build\n     * @param  {String}  arg0 - 模块UMI或者别名\n     * @param  {Regular} arg1 - Regular组件模块\n     * @return {_$$RegularModule} RegularModule模块\n     */\n    _p._$regist = function(_umiAlias, _$$InnerModule){\n        /**\n         * Regular模块对象\n         *\n         * @class   {_$$OuterModule}\n         * @extends {_$$RegularModule}\n         */\n        var _$$OuterModule = _k._$klass();\n        var _pro = _$$OuterModule._$extend(_p._$$RegularModule);\n\n        _pro.__init = function(options){\n            this.__umiAlias = _umiAlias;\n            this._$$InnerModule = _$$InnerModule;\n            this.__super(options);\n        }\n\n        _v._$addEvent(document, 'templateready', function(){\n            _m._$regist(_umiAlias, _$$OuterModule);\n        });\n\n        return _$$OuterModule;\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/dispatcher/test/c/c1.js",
    "content": "/*\n * --------------------------------------------\n * 专辑-专辑详情模块实现文件\n * @version  1.0\n * @author   cheng-lin(cheng-lin@corp.netease.com)\n * --------------------------------------------\n */\ndefine(['{lib}util/dispatcher/module.base.js'],\nfunction(){\n    // variable\n    var _   = NEJ.P,\n        _e  = _('nej.e'),\n        _pm = _('nej.ut'),\n        _pp = _('t.y'),\n        _pro;\n    /**\n     * 专辑详情模块对象\n     * @class   {nm.m.y._$$MAlbumComment}\n     * @extends {nm.m._$$Module}\n     * @property  {String}\n     */\n    _pp._$$ModuleC1 = NEJ.C();\n    _pro = _pp._$$ModuleC1._$extend(_pm._$$AbstractModule);\n\n    _pro.__doBuild = function(){\n        this.__namespace = 'm-c1';\n        this.__supDoBuild();\n        var _html = _e._$getTextTemplate(\n                    this.__namespace+'-module');\n        if (!!_html){\n            this.__body = _e._$html2node(_html);\n        }\n    };\n\n    dispatcher._$loaded('/?/c1',_pp._$$ModuleC1);\n});"
  },
  {
    "path": "src/util/dispatcher/test/c/c2.js",
    "content": "/*\n * --------------------------------------------\n * 专辑-专辑详情模块实现文件\n * @version  1.0\n * @author   cheng-lin(cheng-lin@corp.netease.com)\n * --------------------------------------------\n */\ndefine(['{lib}util/dispatcher/module.base.js'],\nfunction(){\n    // variable\n    var _   = NEJ.P,\n        _e  = _('nej.e'),\n        _pm = _('nej.ut'),\n        _pp = _('t.y'),\n        _pro;\n    /**\n     * 专辑详情模块对象\n     * @class   {nm.m.y._$$MAlbumComment}\n     * @extends {nm.m._$$Module}\n     * @property  {String}\n     */\n    _pp._$$ModuleC2 = NEJ.C();\n    _pro = _pp._$$ModuleC2._$extend(_pm._$$AbstractModule);\n\n    _pro.__doBuild = function(){\n        this.__namespace = 'm-c2';\n        this.__supDoBuild();\n        var _html = _e._$getTextTemplate(\n                    this.__namespace+'-module');\n        if (!!_html){\n            this.__body = _e._$html2node(_html);\n        }\n    };\n\n    dispatcher._$loaded('/?/c2',_pp._$$ModuleC2);\n});"
  },
  {
    "path": "src/util/dispatcher/test/c/index.css",
    "content": "index.css"
  },
  {
    "path": "src/util/dispatcher/test/c/index.js",
    "content": "/*\n * --------------------------------------------\n * 专辑-专辑详情模块实现文件\n * @version  1.0\n * @author   cheng-lin(cheng-lin@corp.netease.com)\n * --------------------------------------------\n */\ndefine(['{lib}util/dispatcher/module.base.js'],\nfunction(){\n    // variable\n    var _   = NEJ.P,\n        _e  = _('nej.e'),\n        _pm = _('nej.ut'),\n        _pp = _('t.y'),\n        _pro;\n    /**\n     * 专辑详情模块对象\n     * @class   {nm.m.y._$$MAlbumComment}\n     * @extends {nm.m._$$Module}\n     * @property  {String}\n     */\n    _pp._$$ModuleC = NEJ.C();\n    _pro = _pp._$$ModuleC._$extend(_pm._$$AbstractModule);\n\n    _pro.__reset = function(_options){\n        this.__supReset(_options);\n    };\n\n    _pro.__onRefresh = function(_options){\n        this.__supOnRefresh(_options);\n        dispatcher._$redirect('/?/c1',{input:{parent:this.__body}});\n        dispatcher._$redirect('/?/c2',{input:{parent:this.__body}});\n    };\n\n    _pro.__doBuild = function(){\n        this.__namespace = 'm-c';\n        this.__supDoBuild();\n        var _html = _e._$getTextTemplate(\n                    this.__namespace+'-module');\n        if (!!_html){\n            this.__body = _e._$html2node(_html);\n        }\n    };\n\n    dispatcher._$loaded('/m/root/c',_pp._$$ModuleC);\n});"
  },
  {
    "path": "src/util/dispatcher/test/dispatcher.2.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>dispatcher2测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit dispatcher2 test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./dispatcher.2.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/dispatcher/test/dispatcher.2.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"dispatcher2\");\n    var _  = NEJ.P,\n        _p = _('nej.ut'),\n        _j = _('nej.j');\n\n\ttest('dispatcher2 single function',function(){\n        stop();\n        var _dispatcher = _p._$$Dispatcher._$allocate();\n        // _dispatcher._$rule([\n        //     {'/m/a':'/m/','/m/c':'/m/d'},  // <---- 此处两条规则匹配与顺序无关\n        //     {'/m/b':/^\\/m\\/b.*$/i},\n        //     {'404':'/m/a'}                 // <---- 模块不存在时定向到/m/a模块\n        // ]);\n        _dispatcher._$rule('title',{\n            '/m/root/':'root',\n            '/m/root/a':'a',\n            '/m/root/b':'b',\n            '/m/root/c':'c',\n            '/m/root/c/?/c1':'c1',\n            '/m/root/c/?/c2':'c2',\n            '/m/root/c/?/c3':'c3'\n        });\n        _dispatcher._$rule('rewrite',{\n            \n        });\n\t});\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}dispatcher.2.test.js',\n    ['{lib}util/dispatcher/dispatcher.2.js'],f);\n});\n  "
  },
  {
    "path": "src/util/dispatcher/test/m/a.html",
    "content": "a.html"
  },
  {
    "path": "src/util/dispatcher/test/m/b.html",
    "content": "b.html"
  },
  {
    "path": "src/util/dispatcher/test/m/c.html",
    "content": "<meta charset=\"utf-8\"/>\n<textarea name=\"txt\" id=\"m-c-module\">\n  <div>c</div>\n</textarea>\n</textarea>\n\n<textarea name=\"js\" data-src=\"../c/index.js\"></textarea>\n"
  },
  {
    "path": "src/util/dispatcher/test/m/c1.html",
    "content": "<meta charset=\"utf-8\"/>\n<textarea name=\"txt\" id=\"m-c1-module\">\n  <div id=\"c1\">c1</div>\n</textarea>\n</textarea>\n\n<textarea name=\"js\" data-src=\"../c/c1.js\"></textarea>\n"
  },
  {
    "path": "src/util/dispatcher/test/m/c2.html",
    "content": "<meta charset=\"utf-8\"/>\n<textarea name=\"txt\" id=\"m-c2-module\">\n  <div id=\"c2\">c2</div>\n</textarea>\n</textarea>\n\n<textarea name=\"js\" data-src=\"../c/c2.js\"></textarea>\n"
  },
  {
    "path": "src/util/dispatcher/test/m/root.html",
    "content": "<meta charset=\"utf-8\"/>\n<textarea name=\"txt\" id=\"m-root-module\">\n  <div>root</div>\n</textarea>\n\n<textarea name=\"js\" data-src=\"../root/index.js\"></textarea>\n"
  },
  {
    "path": "src/util/dispatcher/test/private.module.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>cache测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit privateModule test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t \t<div id=\"template-box\" style=\"display:none;\">\n\n\t      <textarea name=\"html\" data-src=\"m/c.html\"></textarea>\n\n\t      <!-- @MODULE -->\n\t      <textarea name=\"html\" data-src=\"m/root.html\"></textarea>\n\t      <textarea name=\"html\" data-src=\"m/c1.html\"></textarea>\n\t      <textarea name=\"html\" data-src=\"m/c2.html\"></textarea>\n\t      <!-- /@MODULE -->\n\t    </div>\n\t    <div id=\"content-box\"></div>\n\t    <!-- @VERSION -->\n\t    <script>location.config={root:'./'};</script>\n\t    <!-- @DEFINE -->\n\t     <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./private.module.test.js\"></script>\n\t</body>\n</html>\n"
  },
  {
    "path": "src/util/dispatcher/test/private.module.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"privateModule\");\n    var _  = NEJ.P,\n    \t_e = _('nej.e'),\n        _p = _('nej.ut'),\n        _j = _('nej.j');\n\n\ttest('private module show',function(){\n        expect(2);\n        stop();\n        var _dispatcher = _p._$$Dispatcher._$getInstance();\n        // _dispatcher._$rule([\n        //     {'/m/a':'/m/','/m/c':'/m/d'},  // <---- 此处两条规则匹配与顺序无关\n        //     {'/m/b':/^\\/m\\/b.*$/i},\n        //     {'404':'/m/a'}                 // <---- 模块不存在时定向到/m/a模块\n        // ]);\n        _dispatcher._$rule('title',{\n            '/m/root':'root',\n            '/m/root/c':'c',\n            '/?/c1':'c1',\n            '/?/c2':'c2',\n            '/?/c3':'c3'\n        });\n        _e._$parseTemplate('template-box');\n        window.dispatcher = _dispatcher;\n\t    _dispatcher._$active();\n        setTimeout(function(){\n            location.href = '#/m/root/c';\n            setTimeout(function(){\n                notEqual(_e._$getStyle(_e._$get('c1'),'display'),'none');\n                notEqual(_e._$getStyle(_e._$get('c2'),'display'),'none');\n                start();\n            },1000);\n        },1000);\n\t});\n\n    test('private module hidden',function(){\n        expect(2);\n        stop();\n        setTimeout(function(){\n            dispatcher._$hide('/?/c1');\n            dispatcher._$hide('/?/c2');\n            var _cache = dbg.dumpFRG();\n            var _chlidren = _e._$getChildren(_cache);\n            equal('c1',_chlidren[0].id);\n            equal('c2',_chlidren[1].id);\n            start();\n        },10000);\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}private.module.test.js',\n    ['{lib}util/dispatcher/dispatcher.2.js'],f);\n});\n  "
  },
  {
    "path": "src/util/dispatcher/test/root/index.css",
    "content": "index.css"
  },
  {
    "path": "src/util/dispatcher/test/root/index.js",
    "content": "/*\n * --------------------------------------------\n * 专辑-专辑详情模块实现文件\n * @version  1.0\n * @author   cheng-lin(cheng-lin@corp.netease.com)\n * --------------------------------------------\n */\ndefine(['{lib}util/dispatcher/module.base.js'],\nfunction(){\n    // variable\n    var _   = NEJ.P,\n        _e  = _('nej.e'),\n        _pm = _('nej.ut'),\n        _pp = _('t.y'),\n        _pro;\n    /**\n     * 专辑详情模块对象\n     * @class   {nm.m.y._$$MAlbumComment}\n     * @extends {nm.m._$$Module}\n     * @property  {String}\n     */\n    _pp._$$Root = NEJ.C();\n    _pro = _pp._$$Root._$extend(_pm._$$AbstractModule);\n\n    _pro.__reset = function(_options){\n        this.__supReset(_options);\n    };\n\n    _pro.__onShow = function(_options){\n        _options.parent = document.body;\n        this.__supOnShow(_options);\n    };\n\n    _pro.__onRefresh = function(_options){\n        this.__supOnRefresh(_options);\n    };\n\n    _pro.__doBuild = function(){\n        this.__namespace = 'm-root';\n        this.__supDoBuild();\n        var _html = _e._$getTextTemplate(\n                    this.__namespace+'-module');\n        if (!!_html){\n            this.__body = _e._$html2node(_html);\n        }\n    };\n\n    dispatcher._$loaded('/m/root',_pp._$$Root);\n});"
  },
  {
    "path": "src/util/dispatcher/test.js",
    "content": "/*\n * ------------------------------------------\n * 模块基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n\t'base/event',\n\t'util/template/tpl',\n\t'util/history/history',\n\t'./module.js'\n],function(_v,_t,_h,_m,_p,_o,_f,_r){\n\t\n    // aop regist api\n    _m._$regist = \n    _m._$regist._$aop(function(_event){\n        _event.stopped = !0;\n        var _klass = _event.args[1],\n            _inst = _klass._$allocate();\n        _inst.count = 0;\n        _v._$addEvent(\n            location,'urlchange',\n            function(){\n                _inst.count++;\n                var _options = location.parse(location.hash.substr(1));\n                _options.param = _options.query;\n                _options.parent = document.mbody||document.body;\n                _inst._$dispatchEvent(_inst.count==1?'onshow':'onrefresh',_options);\n            }\n        );\n        location.active();\n    });\n    /**\n     * 使用模版测试\n     * @param  {String} 模版ID\n     * @return {Void}\n     */\n    _p._$testByTemplate = function(_tid){\n        _t._$parseTemplate(_tid||'template-box');\n    };\n\t\n\treturn _p;\n});\n"
  },
  {
    "path": "src/util/dragger/dragger.js",
    "content": "/*\n * ------------------------------------------\n * 区域移动功能封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/dragger/dragger */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'util/event'\n],function(NEJ,_k,_e,_v,_t,_p,_o,_f,_r,_pro){\n    /**\n     * 区域移动功能封装\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"box\"></div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/dragger/dragger'\n     * ],function(_t){\n     *     var _dragger = _t._$$Draggable._$allocate({\n     *         body:'box',\n     *         overflow:false,\n     *         direction:0,\n     *         onchange:function(_event){\n     *             // 拖动回调获取位置信息\n     *             var _postion = this._$getPosition();\n     *         },\n     *         ondragend:function(_event){\n     *             // 拖动结束，返回当前位置，或者用_$getPosition接口取到当前位置信息\n     *             var _postion = this._$getPosition();\n     *         }\n     *     });\n     * });\n     * ```\n     * \n     * @class    module:util/dragger/dragger._$$Draggable\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object}      config    - 可选配置参数\n     * @property {Node}        view      - 视窗节点，默认为documentElement或body节点\n     * @property {String|Node} body      - 移动控件节点\n     * @property {String|Node} mbar      - 触发移动节点ID或者对象，默认为body参数输入节点\n     * @property {Boolean}     overflow  - 是否允许超出view范围\n     * @property {Number}      direction - 移动方向，默认为0，0-水平+垂直、1-水平、2-垂直\n     */\n    /**\n     * 位置变化之前触发事件\n     * \n     * @event    module:util/dragger/dragger._$$Draggable#onbeforechange\n     * @param    {Object} event - 位置信息\n     * @property {Number} top   - 离父节点顶部距离\n     * @property {Number} left  - 离父节点左边距离\n     */\n    /**\n     * 位置变化触发事件\n     * \n     * @event    module:util/dragger/dragger._$$Draggable#onchange\n     * @param    {Object} event - 位置信息\n     * @property {Number} top   - 离父节点顶部距离\n     * @property {Number} left  - 离父节点左边距离\n     */\n    /**\n     * 拖拽结束触发事件\n     * \n     * @event    module:util/dragger/dragger._$$Draggable#ondragend\n     * @param    {Object} event - 位置信息\n     * @property {Number} top   - 离父节点顶部距离\n     * @property {Number} left  - 离父节点左边距离\n     */\n    _p._$$Draggable = _k._$klass();\n    _pro = _p._$$Draggable._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/dragger/dragger._$$Draggable#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__overflow = !!_options.overflow;\n        this.__body = _e._$get(_options.body);\n        this.__mbar = _e._$get(_options.mbar)||this.__body;\n        this.__view = _e._$get(_options.view)||_e._$getPageBox();\n        this.__direction = parseInt(_options.direction)||0;\n        this.__doInitDomEvent([[\n            document,'mouseup',\n            this.__onDragEnd._$bind(this)\n        ],[\n            document,'mousemove',\n            this.__onDragging._$bind(this)\n        ],[\n            this.__mbar,'mousedown',\n            this.__onDragStart._$bind(this)\n        ]]);\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/dragger/dragger._$$Draggable#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        this.__onDragEnd();\n        delete this.__body;\n        delete this.__mbar;\n        delete this.__view;\n    };\n    /**\n     * 取移动的最大范围\n     * \n     * @protected\n     * @method module:util/dragger/dragger._$$Draggable#__getMaxRange\n     * @return {Object} 范围值\n     */\n    _pro.__getMaxRange = function(){\n        return {\n            x:this.__view.clientWidth-this.__body.offsetWidth,\n            y:this.__view.clientHeight-this.__body.offsetHeight\n        };\n    };\n    /**\n     * 开始移动\n     * \n     * @protected\n     * @method module:util/dragger/dragger._$$Draggable#__onDragStart\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onDragStart = function(_event){\n        _v._$stop(_event);\n        if (!!this.__offset) return;\n        this.__offset = {\n            x:_v._$pageX(_event),\n            y:_v._$pageY(_event)\n        };\n        this.__maxbox = this.__getMaxRange();\n    };\n    /**\n     * 移动过程\n     * \n     * @protected\n     * @method module:util/dragger/dragger._$$Draggable#__onDragging\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onDragging = function(_event){\n        if (!this.__offset) return;\n        _v._$stop(_event);\n        var _offset = {\n            x:_v._$pageX(_event),\n            y:_v._$pageY(_event)\n        };\n        var _deltax = _offset.x-this.__offset.x,\n            _deltay = _offset.y-this.__offset.y,\n            _top = parseInt(_e._$getStyle(this.__body,'top'))||0,\n            _left = parseInt(_e._$getStyle(this.__body,'left'))||0,\n            _value  = {\n                top:_top+_deltay,\n                left:_left+_deltax\n            };\n        this.__offset = _offset;\n        this._$setPosition(_value);\n    };\n    /**\n     * 结束移动\n     * \n     * @protected\n     * @method module:util/dragger/dragger._$$Draggable#__onDragEnd\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onDragEnd = function(_event){\n        if (!this.__offset) return;\n        delete this.__maxbox;\n        delete this.__offset;\n        this._$dispatchEvent(\n            'ondragend',\n            this._$getPosition()\n        );\n    };\n    /**\n     * 修正位置信息\n     * @param event\n     * @private\n     */\n    _pro.__doFixPosition = function(event){\n        if (!this.__overflow){\n            var maxbox = this.__maxbox||\n                         this.__getMaxRange();\n            event.top  = Math.min(\n                maxbox.y,\n                Math.max(0,event.top)\n            );\n            event.left = Math.min(\n                maxbox.x,\n                Math.max(0,event.left)\n            );\n        }\n    };\n    /**\n     * 设置位置\n     * \n     * 脚本举例\n     * ```javascript\n     * // 在允许范围内设置盒子的位置\n     * _dragger._$setPosition({top:100,left:100});\n     * ```\n     * \n     * @method   module:util/dragger/dragger._$$Draggable#_$setPosition\n     * @param    {Object} arg0 - 位置信息\n     * @property {Number} top  - 垂直位置\n     * @property {Number} left - 水平位置\n     * @return   {Void}\n     */\n    _pro._$setPosition = function(_event){\n        _event.top = Math.round(_event.top);\n        _event.left = Math.round(_event.left);\n        // fix position\n        this.__doFixPosition(_event);\n        this._$dispatchEvent(\n            'onbeforechange',_event\n        );\n        this.__doFixPosition(_event);\n        // update position\n        var _style  = this.__body.style;\n        if (this.__direction==0||\n            this.__direction==2)\n            _style.top  = _event.top+'px';\n        if (this.__direction==0||\n            this.__direction==1)\n            _style.left = _event.left+'px';\n        this._$dispatchEvent('onchange',_event);\n    };\n    /**\n     * 取当前位置\n     * \n     * 脚本举例\n     * ```javascript\n     * _dragger._$getPosition();\n     * ```\n     * \n     * @method module:util/dragger/dragger._$$Draggable#_$getPosition\n     * @return {Object} 当前位置，{top:100,left:100}\n     */\n    _pro._$getPosition = function(){\n        return {\n            left:parseInt(_e._$getStyle(this.__body,'left'),10)||0,\n            top:parseInt(_e._$getStyle(this.__body,'top'),10)||0\n        };\n    };\n    // alias for draggable\n    _p._$$Dragger = _p._$$Draggable;\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/dragger/simple.js",
    "content": "/*\n * ------------------------------------------\n * 简易区域移动功能封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/dragger/simple */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'util/dragger/dragger'\n],function(NEJ,_k,_e,_v,_t,_p,_o,_f,_r,_pro){\n    /**\n     * 区域移动功能封装\n     *\n     * 结构举例\n     * ```html\n     * <div id=\"box\"></div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/dragger/simple'\n     * ],function(_t){\n     *     var _dragger = _t._$$Dragger._$allocate({\n     *         body:'box',\n     *         overflow:false,\n     *         direction:0,\n     *         onchange:function(_event){\n     *             // 拖动回调获取位置信息\n     *             var _postion = this._$getPosition();\n     *         },\n     *         ondragend:function(_event){\n     *             // 拖动结束，返回当前位置，或者用_$getPosition接口取到当前位置信息\n     *             var _postion = this._$getPosition();\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @class    module:util/dragger/simple._$$Dragger\n     * @extends  module:util/event._$$EventTarget\n     *\n     * @param    {Object}      config    - 可选配置参数\n     * @property {Node}        view      - 视窗节点，默认为documentElement或body节点\n     * @property {String|Node} body      - 移动控件节点\n     * @property {String|Node} mbar      - 触发移动节点ID或者对象，默认为body参数输入节点\n     * @property {Boolean}     overflow  - 是否允许超出view范围\n     * @property {Number}      direction - 移动方向，默认为0，0-水平+垂直、1-水平、2-垂直\n     */\n    /**\n     * 位置变化之前触发事件\n     *\n     * @event    module:util/dragger/simple._$$Dragger#onbeforechange\n     * @param    {Object} event - 位置信息\n     * @property {Number} top   - 离父节点顶部距离\n     * @property {Number} left  - 离父节点左边距离\n     */\n    /**\n     * 位置变化触发事件\n     *\n     * @event    module:util/dragger/simple._$$Dragger#onchange\n     * @param    {Object} event - 位置信息\n     * @property {Number} top   - 离父节点顶部距离\n     * @property {Number} left  - 离父节点左边距离\n     */\n    /**\n     * 拖拽结束触发事件\n     *\n     * @event    module:util/dragger/simple._$$Dragger#ondragend\n     * @param    {Object} event - 位置信息\n     * @property {Number} top   - 离父节点顶部距离\n     * @property {Number} left  - 离父节点左边距离\n     */\n    _p._$$Dragger = _k._$klass();\n    _pro = _p._$$Dragger._$extend(_t._$$Draggable);\n    /**\n     * 取初始偏移位置\n     *\n     * @protected\n     * @method module:util/dragger/simple._$$Dragger#__getOffset\n     * @return {Object} 范围值\n     */\n    _pro.__getOffset = function(){\n        return _e._$offset(this.__view);\n    };\n    /**\n     * 开始移动\n     *\n     * @protected\n     * @method module:util/dragger/simple._$$Dragger#__onDragStart\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onDragStart = function(_event){\n        _v._$stop(_event);\n        if (!!this.__offset) return;\n        this.__offset = this.__getOffset();\n        this.__maxbox = this.__getMaxRange();\n    };\n    /**\n     * 移动过程\n     *\n     * @protected\n     * @method module:util/dragger/simple._$$Dragger#__onDragging\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onDragging = function(_event){\n        if (!this.__offset){\n            return;\n        }\n        _v._$stop(_event);\n        var _offset = {\n            x:_v._$clientX(_event),\n            y:_v._$clientY(_event)\n        };\n        this._$setPosition({\n            top:_offset.y-this.__offset.y,\n            left:_offset.x-this.__offset.x\n        });\n    };\n\n    return _p;\n});"
  },
  {
    "path": "src/util/dragger/test/dragger.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>dragger测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n        <style>\n        #box{top:0;left:0;width:100px;height:100px;background:pink;position:absolute;}\n        #view{top:0;left:0;width:300px;height:100px;background:#ccc;position:absolute;}\n        </style>\n\t</head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit dragger test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <div id=\"view\">\n\t\t  <div id=\"box\"></div>\n        </div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./dragger.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/dragger/test/dragger.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"dragger\");\n\tvar _  = NEJ.P,\n\t    _p = _('nej.ut'),\n\t\t_e = _('nej.e');\n\t\n    //开始单元测试\n    test('dragger',function(){\n        // stop();\n        expect(0);\n\t\tvar _box = _e._$get('box');\n\t\tvar _dg = _p._$$Dragger._$allocate({\n\t\t  view:_e._$get('view'),\n\t\t  body:_box,\n\t\t  overflow:false,\n\t\t  direction:0,\n\t\t  onchange:function(_event){\n\t\t  \t// ok(true,'设置位置');\n\t\t  },\n\t\t  ondragend:function(_event){\n\t\t  \t// ok(true,'当前位置top:'+_event.top+'left:'+_event.left);\n\t\t  \t// start();\n\t\t  }\n\t\t})\n    });\n    \n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}dragger.test.js',['{lib}util/dragger/dragger.js'],f);\n});"
  },
  {
    "path": "src/util/editor/area.js",
    "content": "/*\n * ------------------------------------------\n * 富媒体编辑器输入区封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/editor/area */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'base/util',\n    '{platform}editor.js',\n    'util/event',\n    'base/platform'\n],function(NEJ,_k,_e,_v,_u,_h,_t,_m,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 富媒体编辑器输入区封装\n     *\n     * @class     module:util/editor/area._$$EditorArea\n     * @extends   module:util/event._$$EventTarget\n     * @param     {Object} options - 可选配置参数\n     * @property  {Node|String|Function} parent  - 父节点或者编辑器加入父节点执行函数\n     * @property  {String}               style   - 编辑器初始样式\n     * @property  {Boolean}              focus   - 是否自动聚焦\n     * @property  {String}               content - 文本内容\n     */\n    /**\n     * 光标改变事件\n     *\n     * @event  module:util/editor/area._$$EditorArea#onselectionchange\n     */\n    _p._$$EditorArea = _k._$klass();\n    _pro = _p._$$EditorArea._$extend(_t._$$EventTarget);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:util/editor/area._$$EditorArea#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__fopt = {\n            visible:!0,\n            onload:this.__onIFrameLoaded._$bind(this)\n        };\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/editor/area._$$EditorArea#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = (function(){\n        var _cnttpl = '<head><base href=\"#<BSUL>\"/><style>html,body{margin:0;padding:0;border:0;cursor:text;font-size:14px;font-family:Arial;word-wrap:break-word;height:100%;} html{overflow:hidden;}body{overflow:auto;}#<UDCS></style></head><body contenteditable=\"true\"></body>';\n        return function(_options){\n            this.__super(_options);\n            this.__focus = _options.focus;\n            this.__content = _cnttpl\n                .replace('#<UDCS>',_options.style||'')\n                .replace('#<BSUL>',_options.base||location.href);\n            this.__initcnt = _options.content||'';\n            this.__fopt.parent =\n                _e._$get(_options.parent)||document.body;\n            this.__iframe = _e._$createXFrame(this.__fopt);\n        };\n    })();\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/editor/area._$$EditorArea#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        _h.__clearRange(this._$getDocument());\n        delete this.__content;\n        delete this.__fopt.parent;\n        delete this.__initcnt;\n        this.__iframe = _e._$remove(this.__iframe);\n    };\n    /**\n     * 保存选中状态\n     *\n     * @protected\n     * @method module:util/editor/area._$$EditorArea#__doSaveRange\n     * @return {Void}\n     */\n    _pro.__doSaveRange = function(){\n        _h.__saveRange(this._$getDocument());\n    };\n    /**\n     * iframe载入完成触发事件\n     *\n     * @protected\n     * @method module:util/editor/area._$$EditorArea#__onIFrameLoaded\n     * @return {Void}\n     */\n    _pro.__onIFrameLoaded = function(_iframe){\n        var _document = this._$getDocument();\n        _document.open();\n        _document.write(this.__content);\n        if (location.hostname!=document.domain)\n            _document.domain = document.domain;\n        _document.close(); // <- will trigger iframe onload\n        _h.__supportSelectionChange(_document.body);\n        this.__doInitDomEvent([[\n            _document,'click',\n            this.__onDocumentClick._$bind(this)\n        ],[\n            _document,'selectionchange',\n            this.__onSelectionChange._$bind(this)\n        ],[\n            _document,'beforedeactivate',\n            this.__doSaveRange._$bind(this)\n        ],[\n            _document,'keydown',\n            this.__onInputCheck._$bind(this)\n        ],[\n            _document,'mouseup',\n            this.__onInputCheck._$bind(this)\n        ],[\n            _document,'paste',\n            this.__onInputCheck._$bind(this)\n        ],[\n            _document,'drop',\n            this.__onInputCheck._$bind(this)\n        ]]);\n        // init content and focus\n        if (!!this.__initcnt){\n            this._$setContent(this.__initcnt);\n        }\n        if (!!this.__focus){\n            this._$focus();\n            delete this.__focus;\n        }\n    };\n    /**\n     * 文档点击事件\n     *\n     * @protected\n     * @method module:util/editor/area._$$EditorArea#__onDocumentClick\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onDocumentClick = function(_event){\n        _v._$dispatchEvent(document,'click');\n    };\n    /**\n     * 选中内容变化触发事件\n     *\n     * @protected\n     * @method module:util/editor/area._$$EditorArea#__onSelectionChange\n     * @return {Void}\n     */\n    _pro.__onSelectionChange = function(){\n        // TODO something\n        this._$dispatchEvent('onselectionchange');\n    };\n    /**\n     * 输入事件\n     *\n     * @protected\n     * @method  module:util/editor/area._$$EditorArea#__onInputCheck\n     * @return {Void}\n     */\n    _pro.__onInputCheck = function(){\n        if (!!this.__timer){\n            window.clearTimeout(this.__timer);\n        }\n        this.__timer = window.setTimeout(\n            this.__doCompareContent._$bind(this),100\n        );\n    };\n    /**\n     * 比较富文本的内容\n     *\n     * @protected\n     * @method  module:util/editor/area._$$EditorArea#__doCompareContent\n     * @return {Void}\n     */\n    _pro.__doCompareContent = function(){\n        var _document = this._$getDocument();\n        if (!_document) return;\n        var _content = _document.body.innerHTML;\n        if (this.__initcnt!=_content){\n            this.__initcnt = _content;\n            this._$dispatchEvent('oninput',{\n                cont:this._$getContent(),\n                txt:this._$getTextContent()\n            });\n        }\n    };\n\n    /**\n     * 过滤所有style和class标签\n     *\n     * @protected\n     * @method module:util/editor/area._$$EditorArea#__doRemoveStyle\n     * @param  {String} arg0 - 原始富文本内容\n     * @return {String}        过滤后的富文本内容\n     */\n    _pro.__doRemoveStyle = (function(){\n        var _reg0 = /style=\"[^\"]*\"/gi,\n            _reg1 = /style='[^']*'/gi,\n            _reg2 = /style=[^>\\s]*/gi,\n            _reg3 = /class=\"[^\"]*\"/gi,\n            _reg4 = /class='[^']*'/gi,\n            _reg5 = /class=[^>\\s]*/gi;\n        return function(_html){\n            return _html.replace(_reg0,'').replace(_reg1,'').replace(_reg2,'').replace(_reg3,'').replace(_reg4,'').replace(_reg5,'');\n        };\n    })();\n    /**\n     * 过滤所有style和class标签\n     *\n     * @protected\n     * @method module:util/editor/area._$$EditorArea#__doRemoveId\n     * @param  {String} arg0 - 原始富文本内容\n     * @return {String}        过滤后的富文本内容\n     */\n    _pro.__doRemoveId = (function(){\n        var _reg0 = /id=\"[^\"]*\"/gi,\n            _reg1 = /id='[^']*'/gi,\n            _reg2 = /id=[^>\\s]*/gi;\n        return function(_html){\n            return _html.replace(_reg0,'').replace(_reg1,'').replace(_reg2,'');\n        };\n    })();\n    /**\n     * 聚焦编辑器\n     *\n     * @method module:util/editor/area._$$EditorArea#_$focus\n     * @param  {Number} arg0 - 光标位置，默认为0，0-末尾、1-起始、2-不变、3-IE11-bug\n     * @return {Void}\n     */\n    _pro._$focus = function(_cursor){\n        var _document = this._$getDocument();\n        if (!_document) return;\n        _h.__focusRange(_document.body);\n        _h.__moveCursorPosition(\n            _document.body,\n            parseInt(_cursor)||0\n        );\n        this.__onSelectionChange();\n    };\n    /**\n     * 取编辑器文档对象\n     *\n     * @method module:util/editor/area._$$EditorArea#_$getDocument\n     * @return {Node} 文档对象\n     */\n    _pro._$getDocument = function(){\n        return this.__iframe.contentWindow.document;\n    };\n    /**\n     * 取编辑内容\n     *\n     * @param  {Boolean|Number|Object}  默认过滤所有style(只保留background-color,font-size,color样式)，如果是对象，keepStyle表示不过滤style，noId表示过滤id\n     * @return {String} 内容\n     */\n    _pro._$getContent = function(_options){\n        var _document = this._$getDocument(),\n            _noId,_keepStyle,_keepClass;\n        if (_u._$isObject(_options)){\n            _keepClass = _options.keepClass||false;\n            _keepStyle = _options.keepStyle||false;\n            _noId   = _options.noId;\n        }\n        _html = _h.__filterContent(!_document?'':_document.body.innerHTML,_keepClass);\n        if (!_keepStyle){\n            _html = _h.__filterContentStyle(_html);\n        }\n        if (!!_noId){\n            _html = this.__doRemoveId(_html);\n        }\n        return !_h.__filterWordContent?_html:_h.__filterWordContent(_html);\n    };\n    /**\n     * 取纯文本的编辑内容\n     *\n     * @method module:util/editor/area._$$EditorArea#_$getTextContent\n     * @return {String} 内容\n     */\n    _pro._$getTextContent = function(){\n        var _document = this._$getDocument(),\n            _text = _document.body.innerText||\n                    _document.body.textContent;\n        return !_document?'':_text;\n    };\n    /**\n     * 过滤style和class标签\n     *\n     * @method module:util/editor/area._$$EditorArea#_$setContentNoStyle\n     * @return {Void}\n     */\n    _pro._$setContentNoStyle = function(){\n        var _node = this._$getSelectNode();\n        if(!_node) return;\n        var _document = this._$getDocument(),\n            _outer = _node.outerHTML;\n        var _html = !_document?'':_document.body.outerHTML;\n        _html = _html.replace(_outer,this.__doRemoveStyle(_outer));\n        _html = _h.__filterContent(_html);\n        var _content = !_h.__filterWordContent?_html:_h.__filterWordContent(_html);\n        this._$setContent(_content);\n    };\n    /**\n     * 设置内容\n     *\n     * @method module:util/editor/area._$$EditorArea#_$setContent\n     * @param  {String} arg0 - 编辑内容\n     * @return {Void}\n     */\n    _pro._$setContent = function(_content){\n        var _document = this._$getDocument();\n        if (!_document) return;\n        _document.body.innerHTML = _content;\n        this.__onInputCheck();\n    };\n    /**\n     * 执行编辑命令\n     *\n     * @method module:util/editor/area._$$EditorArea#_$execCommand\n     * @param  {String} arg0 - 命令名称\n     * @param  {String} arg1 - 命令值\n     * @param  {String} arg2 - 是否通过style的方式来改变样式，比如superscript命令\n     * @return {Void}\n     */\n    _pro._$execCommand = function(_command,_value,_css){\n        var _document = this._$getDocument();\n        if (!_document) return;\n        // this._$focus(2);\n        _h.__execCommand(_document,'styleWithCSS',false);\n        _h.__execCommand(_document,_command,_value);\n        if (_command == 'inserthtml'){\n            this._$focus(3);\n        }else{\n            this._$focus(2);\n        }\n        this.__onInputCheck();\n    };\n    /**\n     * 查询命令的状态\n     *\n     * @method module:util/editor/area._$$EditorArea#_$queryCommand\n     * @param  {String} arg0 -   命令名称\n     * @param  {String} arg1 -   查询类型，State/Enabled/Value\n     * @return {Variable} 查询结果\n     */\n    _pro._$queryCommand = function(_command,_type){\n        try{\n            var _document = this._$getDocument();\n            return !_document ? null\n                :_document['queryCommand'+_type](_command);\n        }catch(ex){\n            return null;\n        }\n    };\n    /**\n     * 获取选中内容的文本\n     *\n     * @method module:util/editor/area._$$EditorArea#_$getSelectText\n     * @return {String} 文本内容\n     */\n    _pro._$getSelectText = function(){\n        this._$focus(2);\n        return _h.__getSelectText(this._$getDocument());\n    };\n    /**\n     * 获取选择内容的HTML\n     *\n     * @method module:util/editor/area._$$EditorArea#_$getSelectHtml\n     * @return  {String} HTML代码\n     */\n    _pro._$getSelectHtml = function(){\n        this._$focus(2);\n        return _h.__getSelectHtml(this._$getDocument());\n    };\n    /**\n     * 获取选择内容的父节点\n     *\n     * @method module:util/editor/area._$$EditorArea#_$getSelectHtml\n     * @return {Node} 父节点\n     */\n    _pro._$getSelectNode = function(){\n        this._$focus(2);\n        return _h.__getSelectNode(this._$getDocument());\n    };\n    /**\n     * 取编辑区域容器位置大小信息\n     *\n     * @return {Object} 位置大小信息\n     * |     属性         |       含义          |\n     * |     :---         |       :---          |\n     * |     scrollTop    |       滚动垂直偏移  |\n     * |     scrollLeft   |       滚动水平偏移  |\n     * |     clientWidth  |       页面可视宽度  |\n     * |     clientHeight |       页面可视高度  |\n     * |     scrollWidth  |       页面滚动宽度  |\n     * |     scrollHeight |       页面滚动高度  |\n     */\n    _pro._$getAreaBox = function(){\n        var _document = this._$getDocument();\n        return !_document?null:_e._$getPageBox(_document);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/backcolor.js",
    "content": "/*\n * ------------------------------------------\n * 背景色执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/editor/command/backcolor */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/color'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 背景色执行命令封装\n     *\n     * @class   module:util/editor/command/backcolor._$$BackColor\n     * @extends module:util/editor/command/color._$$Color\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$BackColor = _k._$klass();\n    _pro = _p._$$BackColor._$extend(_t0._$$Color);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/backcolor._$$BackColor.command\n     */\n    _p._$$BackColor.command = 'hiliteColor';\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:util/editor/command/backcolor._$$BackColor#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__super();\n        this.__fopt.defaultColor = '#fff';\n    };\n    // regist command implemention\n    _p._$$BackColor._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/blockquote.js",
    "content": "/*\n * ------------------------------------------\n * 引用执行命令封装实现文件\n * @version  1.0\n * @author   cheng-lin(cheng-lin@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/editor/command/blockquote */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 引用执行命令封装\n     *\n     * @class   module:util/editor/command/blockquote._$$Blockquote\n     * @extends module:util/editor/command._$$SimpleCommand\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$Blockquote = _k._$klass();\n    _pro = _p._$$Blockquote._$extend(_t0._$$EditorCommand);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/blockquote._$$Blockquote.command\n     */\n    _p._$$Blockquote.command = 'blockquote';\n\n    /**\n     * 执行命令\n     *\n     * @method module:util/editor/command/blockquote._$$Blockquote#_$execute\n     * @param  {Object} options - 执行参数\n     * @return {Void}\n     */\n    _pro._$execute = function(_options){\n        this.__editor._$execCommand('superscript',false,1);\n    };\n    // regist command implemention\n    _p._$$Blockquote._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/bold.js",
    "content": "/*\n * ------------------------------------------\n * 加粗执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/editor/command/bold */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/simple'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    /**\n     * 加粗执行命令封装\n     *\n     * @class   module:util/editor/command/bold._$$Bold\n     * @extends module:util/editor/command/simple._$$SimpleCommand\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$Bold = _k._$klass();\n    _p._$$Bold._$extend(_t0._$$SimpleCommand);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/bold._$$Bold.command\n     */\n    _p._$$Bold.command = 'bold';\n    // regist command implemention\n    _p._$$Bold._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/card.js",
    "content": "/*\n * ------------------------------------------\n * 命令弹出卡片封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/editor/command/card */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'util/editor/command'\n],function(NEJ,_k,_e,_v,_t0,_p,_o,_f,_r){\n   var _pro;\n    /**\n     * 命令弹出卡片\n     *\n     * @class   module:util/editor/command/card._$$CardCommand\n     * @extends module:util/editor/command._$$EditorCommand\n     * @param   {Object} _options - 可选配置参数\n     */\n    _p._$$CardCommand = _k._$klass();\n    _pro = _p._$$CardCommand._$extend(_t0._$$EditorCommand);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:util/editor/command/card._$$CardCommand#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__fopt = {\n            destroyable:!0,\n            parent:document.body,\n            onchange:this.__onChange._$bind(this)\n        };\n        this.__super();\n    };\n    /**\n     * 卡片内容变化回调，子类实现具体业务逻辑\n     *\n     * @abstract\n     * @method module:util/editor/command/card._$$CardCommand#__onChange\n     * @return {Void}\n     */\n    _pro.__onChange = _f;\n    /**\n     * 显示卡片，子类实现具体业务逻辑\n     *\n     * @abstract\n     * @method module:util/editor/command/card._$$CardCommand#__doShowCard\n     * @return {Void}\n     */\n    _pro.__doShowCard = _f;\n    /**\n     * 执行命令\n     *\n     * @method module:util/editor/command/card._$$CardCommand#_$execute\n     * @param  {Object} options - 执行参数\n     * @return {Void}\n     */\n    _pro._$execute = function(_options){\n        _v._$dispatchEvent(document,'click');\n        var _node = _options.target,\n            _offset = _e._$offset(_node);\n        this.__fopt.top = _offset.y+_node.offsetHeight+1;\n        this.__fopt.left = _offset.x-1;\n        this.__fopt.width = _node.clientWidth;\n        this.__doShowCard();\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/color.js",
    "content": "/*\n * ------------------------------------------\n * 颜色执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** ui/editor/command/color */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/card',\n    'ui/editor/command/simple'\n],function(NEJ,_k,_t0,_i0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 颜色执行命令封装\n     *\n     * @class   module:util/editor/command/color._$$Color\n     * @extends module:util/editor/command/card._$$CardCommand\n     * @param   {Object} _options - 可选配置参数\n     *\n     */\n    _p._$$Color = _k._$klass();\n    _pro = _p._$$Color._$extend(_t0._$$CardCommand);\n    /**\n     * 卡片内容变化回调\n     *\n     * @protected\n     * @method module:util/editor/command/color._$$Color#__onChange\n     * @param  {String} 颜色值\n     * @return {Void}\n     */\n    _pro.__onChange = function(_color){\n        this.__editor._$execCommand(this.__name,_color);\n    };\n    /**\n     * 显示卡片\n     *\n     * @protected\n     * @method module:util/editor/command/color._$$Color#__doShowCard\n     * @return {module:ui/editor/command/simple._$$CardWrapper} 卡片实例\n     */\n    _pro.__doShowCard = function(){\n        _i0._$$SimpleColorCard._$allocate(this.__fopt)._$show();\n    };\n    // regist command implemention\n    _p._$$Color._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/font.js",
    "content": "/*\n * ------------------------------------------\n * 字体/字号执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/font */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'util/editor/command/card',\n    'util/template/jst'\n],function(NEJ,_k,_e,_t0,_t1,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 字体/字号执行命令封装\n     *\n     * @class   module:util/editor/command/font._$$Font\n     * @extends module:util/editor/command/card._$$CardCommand\n     * @param   {Object} arg0 - 可选配置参数\n     */\n    _p._$$Font = _k._$klass();\n    _pro = _p._$$Font._$extend(_t0._$$CardCommand);\n    /**\n     * 取提示信息\n     *\n     * @abstract\n     * @method module:util/editor/command/font._$$Font#__getFontText\n     * @param  {String} 实际值\n     * @return {String} 提示信息\n     */\n    _pro.__getFontText = _f;\n    /**\n     * 字体字号选择回调\n     *\n     * @protected\n     * @method module:util/editor/command/font._$$Font#__onChange\n     * @param  {Object} data - 大小信息\n     * @return {Void}\n     */\n    _pro.__onChange = function(_data){\n        this.__editor._$execCommand(\n            this.__name,_data.value||_data.name);\n    };\n    /**\n     * 查询命令值\n     *\n     * @method module:util/editor/command/font._$$Font#_$queryValue\n     * @param  {Node} node - 命令按钮节点\n     * @return {Void}\n     */\n    _pro._$queryValue = function(_node){\n        var _element = _e._$getByClassName(_node,\n                       'js-t-'+_t1._$seed())[0],\n            _value = this.__getFontText(this\n                         .__editor._$queryCommand(this.__name,'Value'));\n        if (!_element||!_value) return;\n        _element.innerText = _value;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/fontname.js",
    "content": "/*\n * ------------------------------------------\n * 字体执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/fontname */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/font',\n    'ui/editor/command/fontname'\n],function(NEJ,_k,_t0,_i0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 字体执行命令封装\n     * @class   module:util/editor/command/fontname._$$FontName\n     * @extends module:util/editor/command/font._$$Font\n     * @param   {Object} 可选配置参数\n     *\n     */\n    _p._$$FontName = _k._$klass();\n      _pro = _p._$$FontName._$extend(_t0._$$Font);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/fontname._$$FontName.command\n     */\n    _p._$$FontName.command = 'fontName';\n    /**\n     * 显示卡片\n     *\n     * @protected\n     * @method module:util/editor/command/fontname._$$FontName#__doShowCard\n     * @return {Void}\n     */\n    _pro.__doShowCard = function(){\n        _i0._$$FontNameCard._$allocate(this.__fopt)._$show();\n    };\n    /**\n     * 取提示信息\n     *\n     * @protected\n     * @method module:util/editor/command/fontname._$$FontName#__getFontText\n     * @param  {String} arg0 - 实际值\n     * @return {String} 提示信息\n     */\n    _pro.__getFontText = (function(){\n        var _reg = /['\"]/g;\n        return function(_value){\n            if(!_value)\n                return;\n            return _i0._$$FontNameCard._$getText(\n                      _value.replace(_reg,''))||_value;\n        };\n    })();\n    // regist command implemention\n    _p._$$FontName._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/fontsize.js",
    "content": "/*\n * ------------------------------------------\n * 字号大小执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/fontsize */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/font',\n    'ui/editor/command/fontsize'\n],function(NEJ,_k,_t0,_i0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 字号大小执行命令封装\n     *\n     * @class   module:util/editor/command/fontsize._$$FontSize\n     * @extends module:util/editor/command/font._$$Font\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$FontSize = _k._$klass();\n    _pro = _p._$$FontSize._$extend(_t0._$$Font);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/backcolor._$$FontSize.command\n     */\n    _p._$$FontSize.command = 'fontSize';\n    /**\n     * 显示卡片\n     *\n     * @protected\n     * @method module:util/editor/command/fontsize._$$FontSize#__doShowCard\n     * @return {Void}\n     */\n    _pro.__doShowCard = function(){\n        _i0._$$FontSizeCard._$allocate(this.__fopt)._$show();\n    };\n    /**\n     * 取提示信息\n     *\n     * @protected\n     * @method module:util/editor/command/fontsize._$$FontSize#__getFontText\n     * @param  {String} arg0 - 实际值\n     * @return {String} 提示信息\n     */\n    _pro.__getFontText = function(_value){\n        return _i0._$$FontSizeCard._$getText(_value)||'标准';\n    };\n    // regist command implemention\n    _p._$$FontSize._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/forecolor.js",
    "content": "/*\n * ------------------------------------------\n * 文字颜色执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/forecolor */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/color'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 文字颜色执行命令封装\n     *\n     * @class   module:util/editor/command/forecolor._$$ForeColor\n     * @extends module:util/editor/command/color._$$Color\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$ForeColor = _k._$klass();\n    _pro = _p._$$ForeColor._$extend(_t0._$$Color);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/forecolor._$$ForeColor.command\n     */\n    _p._$$ForeColor.command = 'foreColor';\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:util/editor/command/forecolor._$$ForeColor#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__super();\n        this.__fopt.defaultColor = '#000';\n    };\n    // regist command implemention\n    _p._$$ForeColor._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/format.js",
    "content": "/*\n * ------------------------------------------\n * 清除样式命令封装实现文件\n * @version  1.0\n * @author   cheng-lin(cheng-lin@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/format */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    /**\n     * 清除样式命令封装\n     *\n     * @class   module:util/editor/command/format._$$Format\n     * @extends module:util/editor/command._$$EditorCommand\n     * @param   {Object} 可选配置参数\n     */\n    _p._$$Format = _k._$klass();\n    _pro = _p._$$Format._$extend(_t0._$$EditorCommand);\n    /**\n     * 命令名称\n     * @const {String} module:util/editor/command/format._$$Format.command\n     */\n    _p._$$Format.command = 'format';\n\n    /**\n     * 执行命令\n     *\n     * @method  module:util/editor/command/format._$$Format#_$execute\n     * @return {Void}\n     */\n    _pro._$execute = function(){\n        this.__editor._$setContentNoStyle();\n    };\n    // regist command implemention\n    _p._$$Format._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/insertorderedlist.js",
    "content": "/*\n * ------------------------------------------\n * 有序列表执行命令封装实现文件\n * @version  1.0\n * @author   cheng-lin(cheng-lin@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/insertorderedlist */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/simple'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    /**\n     * 有序列表执行命令封装\n     *\n     * @class   module:util/editor/command/insertorderedlist._$$InsertOrderedList\n     * @extends module:util/editor/command/simple._$$SimpleCommand\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$InsertOrderedList = _k._$klass();\n    _p._$$InsertOrderedList._$extend(_t0._$$SimpleCommand);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/insertorderedlist._$$InsertOrderedList.command\n     */\n    _p._$$InsertOrderedList.command = 'insertorderedlist';\n    // regist command implemention\n    _p._$$InsertOrderedList._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/insertunorderedlist.js",
    "content": "/*\n * ------------------------------------------\n * 无序列表执行命令封装实现文件\n * @version  1.0\n * @author   cheng-lin(cheng-lin@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/insertunorderedlist */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/simple'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    /**\n     * 无序列表执行命令封装\n     *\n     * @class   module:util/editor/command/insertunorderedlist._$$InsertUnorderedList\n     * @extends module:util/editor/command/simple._$$SimpleCommand\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$InsertUnorderedList = _k._$klass();\n    _p._$$InsertUnorderedList._$extend(_t0._$$SimpleCommand);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/insertunorderedlist._$$SimpleCommand.command\n     */\n    _p._$$InsertUnorderedList.command = 'insertunorderedlist';\n    // regist command implemention\n    _p._$$InsertUnorderedList._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/italic.js",
    "content": "/*\n * ------------------------------------------\n * 斜体执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/italic */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/simple'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    /**\n     * 斜体执行命令封装\n     *\n     * @class   module:util/editor/command/italic._$$Italic\n     * @extends module:util/editor/command/simple._$$SimpleCommand\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$Italic = _k._$klass();\n    _p._$$Italic._$extend(_t0._$$SimpleCommand);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/italic._$$Italic.command\n     */\n    _p._$$Italic.command = 'italic';\n    // regist command implemention\n    _p._$$Italic._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/justifycenter.js",
    "content": "/*\n * ------------------------------------------\n * 居中对齐执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/editor/command/justifycenter */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/simple'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    /**\n     * 居中对齐执行命令封装\n     *\n     * @class   module:util/editor/command/justifycenter._$$JustifyCenter\n     * @extends module:util/editor/command/simple._$$SimpleCommand\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$JustifyCenter = _k._$klass();\n    _p._$$JustifyCenter._$extend(_t0._$$SimpleCommand);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/justifycenter._$$JustifyCenter.command\n     */\n    _p._$$JustifyCenter.command = 'justifyCenter';\n    // regist command implemention\n    _p._$$JustifyCenter._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/justifyleft.js",
    "content": "/*\n * ------------------------------------------\n * 左对齐执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/justifyleft */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/simple'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    /**\n     * 左对齐执行命令封装\n     *\n     * @class   module:util/editor/command/justifyleft._$$JustifyLeft\n     * @extends module:util/editor/command/simple._$$SimpleCommand\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$JustifyLeft = _k._$klass();\n    _p._$$JustifyLeft._$extend(_t0._$$SimpleCommand);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/justifyleft._$$JustifyLeft.command\n     */\n    _p._$$JustifyLeft.command = 'justifyLeft';\n    // regist command implemention\n    _p._$$JustifyLeft._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/justifyright.js",
    "content": "/*\n * ------------------------------------------\n * 右对齐执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/justifyright */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/simple'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    /**\n     * 右对齐执行命令封装\n     *\n     * @class   module:util/editor/command/justifyright._$$JustifyRight\n     * @extends module:util/editor/command/simple._$$SimpleCommand\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$JustifyRight = _k._$klass();\n    _p._$$JustifyRight._$extend(_t0._$$SimpleCommand);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/justifyright._$$JustifyRight.command\n     */\n    _p._$$JustifyRight.command = 'justifyRight';\n    // regist command implemention\n    _p._$$JustifyRight._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/link.js",
    "content": "/*\n * ------------------------------------------\n * 超链接执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/link */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/card',\n    'ui/editor/command/link'\n],function(NEJ,_k,_t0,_i0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 超链接执行命令封装\n     *\n     * @class   module:util/editor/command/link._$$Link\n     * @extends module:util/editor/command/card._$$CardCommand\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$Link = _k._$klass();\n    _pro = _p._$$Link._$extend(_t0._$$CardCommand);\n    /*\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/link._$$Link.command\n     */\n    _p._$$Link.command = 'link';\n\n    /**\n     * 卡片内容变化回调，子类实现具体业务逻辑\n     *\n     * @protected\n     * @method   module:util/editor/command/link._$$Link#__onChange\n     * @param    {Object} _link - 链接地址对象\n     * @property {String} name  - 链接名称\n     * @property {String} href  - 链接地址\n     * @return   {Void}\n     */\n    _pro.__onChange = function(_link){\n        if(!_link)\n            return;\n        var _text = (_link.name != '') ? _link.name : _link.href;\n        this.__editor._$execCommand('inserthtml','<a target=\"_blank\" href=\"'\n                        + _link.href + '\">'+ _text +'</a>');\n        this.__editor._$focus(3);\n    };\n\n    /**\n     * 显示卡片，一般子类重写\n     *\n     * @protected\n     * @method module:util/editor/command/link._$$Link#__doShowCard\n     * @return {Void}\n     */\n    _pro.__doShowCard = function(){\n        this.__fopt.name = this.__editor._$getSelectText();\n        this.__linkCard = this.__onShowCard();\n        this.__linkCard._$show();\n        this.__linkCard._$doFocus();\n    };\n\n    /**\n     * 子类实现显示具体卡片\n     *\n     * @protected\n     * @method module:util/editor/command/link._$$Link#__onShowCard\n     * @return {Void}\n     */\n    _pro.__onShowCard = function(){\n        return _i0._$$LinkCard._$allocate({\n            draggable: true,\n            destroyable: true,\n            maskclazz: 'm-mask',\n            name: this.__fopt.name,\n            title: '添加超链接',\n            onchange: this.__onChange._$bind(this),\n            onErrorLink: this.__onError._$bind(this)\n        });\n    };\n    /**\n     * 链接错误提示\n     *\n     * @protected\n     * @method module:util/editor/command/link._$$Link#__onError\n     * @param  {Object} type - 错误类型\n     * @return {Void}\n     */\n    _pro.__onError = function(){\n        this.__linkCard.__showErrorTips('请输入合法的链接地址（http://或https://）');\n    };\n\n    // regist command implemention\n    _p._$$Link._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/removeformat.js",
    "content": "/*\n * ------------------------------------------\n * 清除格式执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/removeformat */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/simple'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    /**\n     * 清除格式执行命令封装\n     *\n     * @class   module:util/editor/command/removeformat._$$RemoveFormat\n     * @extends module:util/editor/command/simple._$$SimpleCommand\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$RemoveFormat = _k._$klass();\n    _p._$$RemoveFormat._$extend(_t0._$$SimpleCommand);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/removeformat._$$RemoveFormat.command\n     */\n    _p._$$RemoveFormat.command = 'RemoveFormat';\n    // regist command implemention\n    _p._$$RemoveFormat._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/simple.js",
    "content": "/*\n * ------------------------------------------\n * 简易命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/simple */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 简易命令封装\n     *\n     * @class   module:util/editor/command/simple._$$SimpleCommand\n     * @extends module:util/editor/command._$$EditorCommand\n     * @param   {Object} options - 可选配置参数\n     *\n     */\n    _p._$$SimpleCommand = _k._$klass();\n      _pro = _p._$$SimpleCommand._$extend(_t0._$$EditorCommand);\n    /**\n     * 执行命令\n     *\n     * @method module:util/editor/command/simple._$$SimpleCommand#_$execute\n     * @return {Void}\n     */\n    _pro._$execute = function(){\n        this.__editor._$execCommand(this.__name);\n    };\n    /**\n     * 查询命令是否已经执行\n     *\n     * @method module:util/editor/command/simple._$$SimpleCommand#_$queryState\n     * @return {Boolean} 是否已经被执行，返回null表示不做处理\n     */\n    _pro._$queryState = function(){\n        return this.__editor._$queryCommand(this.__name,'State');\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/space.js",
    "content": "/*\n * ------------------------------------------\n * 空格执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/space */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 空格执行命令封装\n     * @class   module:util/editor/command/space._$$Blank\n     * @extends module:util/editor/command._$$EditorCommand\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$Blank = _k._$klass();\n    _pro = _p._$$Blank._$extend(_t0._$$EditorCommand);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/space._$$Blank.command\n     */\n    _p._$$Blank.command = 'space';\n    /**\n     * 执行命令\n     *\n     * @method module:util/editor/command/space._$$Blank#_$execute\n     * @return {Void}\n     */\n    _pro._$execute = function(){\n        this.__editor._$execCommand('inserthtml','　');\n    };\n    // regist command implemention\n    _p._$$Blank._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/strikethrough.js",
    "content": "/*\n * ------------------------------------------\n * 删除线执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/strikethrough */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/simple'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    /**\n     * 删除线执行命令封装\n     *\n     * @class   module:util/editor/command/strikethrough._$$StrikeThrough\n     * @extends module:util/editor/command/simple._$$SimpleCommand\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$StrikeThrough = _k._$klass();\n    _p._$$StrikeThrough._$extend(_t0._$$SimpleCommand);\n    /**\n     * 命令名称\n     * @const {String} module:util/editor/command/strikethrough._$$StrikeThrough.command\n     */\n    _p._$$StrikeThrough.command = 'strikethrough';\n    // regist command implemention\n    _p._$$StrikeThrough._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/superscript.js",
    "content": "/*\n * ------------------------------------------\n * 加粗执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/superscript */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/simple'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    /**\n     * 加粗执行命令封装\n     *\n     * @class   module:util/editor/command/superscript._$$SuperScript\n     * @extends module:util/editor/command/simple._$$SimpleCommand\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$SuperScript = _k._$klass();\n    _p._$$SuperScript._$extend(_t0._$$SimpleCommand);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/superscript._$$SuperScript.command\n     */\n    _p._$$SuperScript.command = 'superscript';\n    // regist command implemention\n    _p._$$SuperScript._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/underline.js",
    "content": "/*\n * ------------------------------------------\n * 下划线执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/underline */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/editor/command/simple'\n],function(NEJ,_k,_t0,_p,_o,_f,_r){\n    /**\n     * 下划线执行命令封装\n     *\n     * @class   module:util/editor/command/underline._$$UnderLine\n     * @extends module:util/editor/command/simple._$$SimpleCommand\n     * @param   {Object} options - 可选配置参数\n     */\n    _p._$$UnderLine = _k._$klass();\n    _p._$$UnderLine._$extend(_t0._$$SimpleCommand);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/underline._$$UnderLine.command\n     */\n    _p._$$UnderLine.command = 'underline';\n    // regist command implemention\n    _p._$$UnderLine._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/command/uploadimage.js",
    "content": "/*\n * ------------------------------------------\n * 图片上传执行命令封装实现文件\n * @version  1.0\n * @author   cheng-lin(cheng-lin@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/command/uploadimage */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    'util/editor/command/card',\n    'ui/editor/command/uploadimage'\n],function(NEJ,_k,_u,_t0,_i0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 左对齐执行命令封装\n     *\n     * @class   module:util/editor/command/uploadimage._$$UploadImage\n     * @extends module:util/editor/command/card._$$CardCommand\n     * @param   {Object} arg0 - 可选配置参数\n     */\n    _p._$$UploadImage = _k._$klass();\n    _pro = _p._$$UploadImage._$extend(_t0._$$CardCommand);\n    /**\n     * 命令名称\n     *\n     * @const {String} module:util/editor/command/uploadimage._$$UploadImage.command\n     */\n    _p._$$UploadImage.command = 'uploadImage';\n\n    /**\n     * 显示卡片，一般子类重写\n     *\n     * @protected\n     * @method module:util/editor/command/uploadimage._$$UploadImage#__doShowCard\n     * @return {Void}\n     */\n    _pro.__doShowCard = function(){\n        this.__onShowCard();\n    };\n\n    /**\n     * 子类实现显示具体卡片\n     *\n     * @protected\n     * @method module:util/editor/command/uploadimage._$$UploadImage#__onShowCard\n     * @return {Void}\n     */\n    _pro.__onShowCard = function(){\n        if (!this.__uploadCard)\n        this.__uploadCard = _i0._$$UploadImageCard._$allocate({\n                onchange:this.__onChange._$bind(this)\n            });\n        this.__uploadCard._$show();\n    };\n\n    /**\n     * 卡片内容变化回调，子类实现具体业务逻辑\n     *\n     * @protected\n     * @method module:util/editor/command/uploadimage._$$UploadImage#__onChange\n     * @param  {Object} arg0 - 插入图片命令\n     * @param  {Object} arg1 - 图片对象\n     * @return {Void}\n     */\n    _pro.__onChange = function(_commend,_photoObj){\n        this.__editor._$focus(2);\n        var _id = 0,_url;\n        if(!!_photoObj.ourl && _photoObj.ourl.indexOf('.gif') > 0){\n            //gif图片\n            _url = _photoObj.ourl;\n            if(!!_photoObj.photoGarbageIds){\n                var _ids = _photoObj.photoGarbageIds.split(',');\n                _u._$forEach(_ids,function(_item,_index){\n                    if(_item.search('ourl') >= 0)\n                        _id = _item.split(':')[1];\n                },this);\n            }\n        }else{\n            _url = _photoObj.userDef2Url;\n            if(!!_photoObj.photoGarbageIds){\n                var _ids = _photoObj.photoGarbageIds.split(',');\n                _u._$forEach(_ids,function(_item,_index){\n                    if(_item.search('userdef2url') >= 0)\n                        _id = _item.split(':')[1];\n                },this);\n            }\n        }\n        var _html = '<img style=\"max-width:520px;\" src=' + _url + ' id='+ _id +' />';\n        this.__editor._$execCommand(_commend,_html);\n    };\n\n    // regist command implemention\n    _p._$$UploadImage._$regist();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut.cmd'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/editor/command.js",
    "content": "/*\n * ------------------------------------------\n * 富媒体编辑器执行命令封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/editor/command */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/event'\n],function(NEJ,_k,_t,_p,_o,_f,_r){\n    var _impls = {},\n        _pro;\n    /**\n     * 富媒体编辑器执行命令封装\n     *\n     * 子类实现具体命令时注意：\n     * - 指定命令识别名称，通过指定类的name属性实现\n     * - 实现命令的具体业务逻辑，通过重写_$execute接口实现\n     *\n     * @class     module:util/editor/command._$$EditorCommand\n     * @extends   module:util/event._$$EventTarget\n     * @param     {Object}                  arg0    - 可选配置参数\n     * @property  {nej.ut._$$EditorArea}    area    - 编辑器核心\n     * @property  {nej.ut._$$EditorToolBar} toolbar - 工具栏实例\n     */\n    _p._$$EditorCommand = _k._$klass();\n    _pro = _p._$$EditorCommand._$extend(_t._$$EventTarget);\n    /**\n     * 注册命令实现\n     *\n     * @method module:util/editor/command._$$EditorCommand._$regist\n     * @return {Void}\n     */\n    _p._$$EditorCommand._$regist = function(){\n        _impls[this.command] = this;\n    };\n    /**\n     * 取命令实现构造\n     *\n     * @method module:util/editor/command._$$EditorCommand._$getImpl\n     * @param  {String} arg0 - 命令名称\n     * @return {nej.ut._$$EditorCommand} 命令实现\n     */\n    _p._$$EditorCommand._$getImpl = function(_command){\n        return _impls[_command]||null;\n    };\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:util/editor/command._$$EditorCommand#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__name = this.constructor.command;\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/editor/command._$$EditorCommand#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__editor  = _options.area;\n        this.__toolbar = _options.toolbar;\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/editor/command._$$EditorCommand#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__editor;\n        delete this.__toolbar;\n    };\n    /**\n     * 执行命令，子类实现具体业务逻辑\n     *\n     * @abstract\n     * @method module:util/editor/command._$$EditorCommand#_$execute\n     * @param  {Object} arg0 - 执行参数\n     * @return {Void}\n     */\n    _pro._$execute = _f;\n    /**\n     * 查询命令值，子类实现具体业务逻辑\n     *\n     * @abstract\n     * @method module:util/editor/command._$$EditorCommand#_$queryValue\n     * @param  {Node} arg0 - 命令按钮节点\n     * @return {Void}\n     */\n    _pro._$queryValue = _f;\n    /**\n     * 查询命令是否已经执行，子类重写具体业务逻辑\n     *\n     * @method module:util/editor/command._$$EditorCommand#_$queryState\n     * @return {Boolean} 是否已经被执行，返回null表示不做处理\n     */\n    _pro._$queryState = function(){\n        return null;\n    };\n    /**\n     * 查询命令是否允许被执行，子类重写具体业务逻辑\n     *\n     * @method module:util/editor/command._$$EditorCommand#_$queryEnabled\n     * @return {Boolean} 是否允许被执行，返回null表示不做处理\n     */\n    _pro._$queryEnabled = function(){\n        return null;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/demo/text.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <title>NEJ实例 - 文本编辑器</title>\n    <meta charset=\"utf-8\" />\n    <style>\n        #abc{width:500px;height:300px;border:1px solid #aaa;}\n        #abc iframe{width:100%;height:100%;}\n    </style>\n</head>\n<body>\n\n<div id=\"abc\"></div>\n\n<script src=\"../../../define.js\"></script>\n<script>\n    NEJ.define([\n        '../text.js'\n    ],function(x){\n        x._$$Editor._$allocate({\n            parent:'abc'\n        });\n    });\n</script>\n</body>\n</html>"
  },
  {
    "path": "src/util/editor/editor.js",
    "content": "/*\n * ------------------------------------------\n * 富媒体编辑器封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/editor */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    'util/event',\n    'util/editor/area',\n    'util/editor/toolbar',\n    'util/editor/command'\n],function(NEJ,_k,_u,_t,_t0,_t1,_t2,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 富媒体编辑器封装\n     *\n     * @class     module:util/editor/editor._$$Editor\n     * @extends   module:util/event._$$EventTarget\n     * @param     {Object}                  arg0    - 可选配置参数\n     * @property  {nej.ut._$$EditorArea}    area    - 编辑器核心区\n     * @property  {nej.ut._$$EditorToolbar} toolbar - 编辑器工具栏\n     */\n    _p._$$Editor = _k._$klass();\n    _pro = _p._$$Editor._$extend(_t._$$EventTarget);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:util/editor/editor._$$Editor#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__copt = {};\n        this.__impl = {};\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/editor/editor._$$Editor#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = (function(){\n        var _doRegist = function(){\n            this._$registCommand(\n                 _t2._$$EditorCommand\n                   ._$getImpl(arguments[1]));\n        };\n        return function(_options){\n            this.__super(_options);\n            // check editor toolbar\n            var _toolbar = _options.toolbar,\n                _isok = _toolbar instanceof\n                        _t1._$$EditorToolbar;\n            !_isok ? _toolbar = null\n                   : this.__copt.toolbar = _toolbar;\n            if (!!_toolbar){\n                _toolbar._$setEvent('oncommand',\n                    this.__onCommand._$bind(this));\n                _u._$forIn(_toolbar\n                  ._$getCommandList(),_doRegist,this);\n            }\n            // check editor area\n            var _area = _options.area,\n                _isok = _area instanceof\n                        _t0._$$EditorArea;\n            !_isok ? _area = null\n                   : this.__copt.area = _area;\n            if (!!_area){\n                _area._$setEvent('onselectionchange',\n                    this.__onSelectionChange._$bind(this));\n            }\n        };\n    })();\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/editor/editor._$$Editor#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = (function(){\n        var _doClearImpl = function(_impl,_key,_map){\n            if (_impl instanceof _t2._$$EditorCommand)\n                _impl._$recycle();\n            delete _map[_key];\n        };\n        return function(){\n            this.__super();\n            if (!!this.__copt.area){\n                this.__copt.area._$recycle();\n                delete this.__copt.area;\n            }\n            if (!!this.__copt.toolbar){\n                this.__copt.toolbar._$recycle();\n                delete this.__copt.toolbar;\n            }\n            _u._$forIn(this.__impl,_doClearImpl);\n        };\n    })();\n    /**\n     * 取命令实现实例\n     *\n     * @protected\n     * @method module:util/editor/editor._$$Editor#__getCommandImpl\n     * @param  {String} arg0 - 命令名称\n     * @return {nej.ut._$$EditorCommand} 命令实现实例\n     */\n    _pro.__getCommandImpl = function(_command){\n        var _impl = this.__impl[_command];\n        if (!_impl) return null;\n        if (!(_impl instanceof _t2._$$EditorCommand)){\n            _impl = _impl._$allocate(this.__copt);\n            this.__impl[_command] = _impl;\n        }\n        return _impl;\n    };\n    /**\n     * 执行命令触发事件\n     *\n     * @protected\n     * @method module:util/editor/editor._$$Editor#__onCommand\n     * @param  {Object} arg0 - 命令信息\n     * @return {Void}\n     */\n    _pro.__onCommand = function(_event){\n        this.__getCommandImpl(_event.name)\n            ._$execute({target:_event.node});\n        this.__copt.area._$focus(2);\n    };\n    /**\n     * 编辑器选择内容变化触发事件\n     *\n     * @protected\n     * @method module:util/editor/editor._$$Editor#__onSelectionChange\n     * @return {Void}\n     */\n    _pro.__onSelectionChange = (function(){\n        var _doSyncToolbar = function(_node,_command){\n            var _impl = this.__getCommandImpl(_command);\n            if (!_impl) return;\n            var _toolbar = this.__copt.toolbar,\n                _value = _impl._$queryState();\n            if (_value!=null)\n                _toolbar._$select(_command,_value);\n            var _value = _impl._$queryEnabled();\n            if (_value!=null)\n                _toolbar._$disable(_command,!_value);\n            _impl._$queryValue(_node);\n        };\n        return function(){\n            var _toolbar = this.__copt.toolbar;\n            if (!_toolbar) return;\n            _u._$forIn(_toolbar.\n               _$getCommandList(),_doSyncToolbar,this);\n        };\n    })();\n    /**\n     * 注册命令实现\n     *\n     * @method module:util/editor/editor._$$Editor#_$registCommand\n     * @param  {Array|nej.ut._$$EditorCommand} arg0 - 命令实现类构造\n     * @return {Void}\n     */\n    _pro._$registCommand = function(_class){\n        if (!_u._$isArray(_class)){\n            var _name = (_class||_o).command;\n            if (!!_name)\n                this.__impl[_name] = _class;\n            return;\n        }\n        _u._$forEach(_class,this._$registCommand,this);\n    };\n    /**\n     * 设置编辑内容\n     *\n     * @method module:util/editor/editor._$$Editor#_$setContent\n     * @param  {String} arg0 - 编辑内容\n     * @return {Void}\n     */\n    _pro._$setContent = function(_content){\n        if (!!this.__copt.area)\n            this.__copt.area._$setContent(_content);\n    };\n    /**\n     * 取编辑内容\n     *\n     * @param  {Boolean|Number|Object}  默认过滤所有style(只保留background-color,font-size,color样式)，如果是对象，keepStyle表示不过滤style，noId表示过滤id\n     * @method module:util/editor/editor._$$Editor#_$getContent\n     * @return {String} 编辑内容\n     */\n    _pro._$getContent = function(_options){\n        return !this.__copt.area ? ''\n               :this.__copt.area._$getContent(_options);\n    };\n\n     /**\n     * 取纯文本编辑内容\n     *\n     * @method module:util/editor/editor._$$Editor#_$getTextContent\n     * @return {String} 编辑内容\n     */\n    _pro._$getTextContent = function(){\n        return !this.__copt.area ? ''\n               :this.__copt.area._$getTextContent();\n    };\n    /**\n     * 取编辑区实例\n     *\n     * @method module:util/editor/editor._$$Editor#_$getArea\n     * @return {nej.ut._$$EditorArea}\n     */\n    _pro._$getArea = function(){\n        return this.__copt.area;\n    };\n    /**\n     * 取工具条实例\n     *\n     * @method module:util/editor/editor._$$Editor#_$getToolbar\n     * @return {nej.ut._$$EditorToolbar}\n     */\n    _pro._$getToolbar = function(){\n        return this.__copt.toolbar;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/editor/platform/editor.js",
    "content": "/**\n * ------------------------------------------\n * 富文本编辑器接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/element',\n    'base/platform'\n],function(_e,_m,_p,_o,_f,_r){\n    var __empty    = /(?:<(p|div)>(?:\\&nbsp\\;|<br\\/?>)<\\/\\1>|<br\\/?>|\\&nbsp\\;|\\s)+$/gi, // empty content\n        __reg_cls0 = /(?:class|lang)=\"(mso)?[^\"]*\"/gi,\n        __reg_cls1 = /(?:class|lang)='(mso)?[^']*'/gi,\n        __reg_cls2 = /(?:class|lang)=(mso)?[^>\\s]*/gi,// IE7/8 hack\n        __reg_ccm  = /(?:<!--)[^>]*(?:-->)/gi,\n        __reg_st0  = /(?:<[^>]* style)=\"([^\"]*)\"/gi,\n        __reg_st1  = /(?:<[^>]* style)='([^']*)'/gi,\n        __reg_st2  = /(?:<[^>]* style)=([^>\\s]*)/gi,// IE7/8 hack\n        __reg_bgc  = /(?:background-color:|text-align:|color:)([^;]*)(;)*/gi;//clear class,lang\n    /**\n     * 取节点所在的窗体对象\n     * @param  {Node} _node 节点\n     * @return {Window}     窗体\n     */\n    _p.__getWindow = function(_node){\n        var _document = _p.__getDocument(_node);\n        return _document.defaultView||_document.parentWindow||_document.window||_document;\n    };\n    /**\n     * 取节点关联的文档对象\n     * @param  {Node} _node 节点\n     * @return {Document}   文档对象\n     */\n    _p.__getDocument = function(_node){\n        return _node.ownerDocument||_node;\n    };\n    /**\n     * 取选择区对象\n     * @param  {Window} _window 窗体对象\n     * @return {DOMSelection}   选择区对象\n     */\n    _p.__getSelection = function(_window){\n        if (!!_window.getSelection)\n            return _window.getSelection();\n        var _document = _window.document;\n        if (!!_document.getSelection)\n            return _document.getSelection();\n        if (!!_document.selection)\n            return _document.selection;\n        return null;\n    };\n    /**\n     * 取选择区范围操作对象\n     * @param  {Window} _window 窗体对象\n     * @return {Range}          范围操作对象\n     */\n    _p.__getRange = function(_window){\n        _window = _p.__getWindow(_window);\n        var _selection = _p.__getSelection(_window);\n        if (!_selection)\n            return null;\n        if (!!_selection.getRangeAt){\n            return _selection.getRangeAt(0);\n        }\n        if (!!_selection.createRange)\n            return _selection.createRange();\n        return null;\n    };\n    /**\n     * 获取选中内容的文本\n     * @return {String} 文本内容\n     */\n    _p.__getSelectText = function(_document){\n        var _range = this.__getRange(_document);\n        if (!_range) return '';\n        return _range.toString()||_range.cloneContents().textContent||_range.commonAncestorContainer.data;\n    };\n    /**\n     * 获取选中内容的html\n     * @param  {Object} _document\n     * @return {String} 选中内容的html\n     */\n    _p.__getSelectHtml = function(_document){\n        var _range = this.__getRange(_document);\n        if (!_range) return '';\n        var _ntmp = _e._$create('div');\n        _ntmp.appendChild(_range.cloneContents());\n        return _ntmp.innerHTML;\n    };\n    /**\n     * 获取选中内容的父节点\n     * @param  {Object} _document\n     * @return {Node|String} 选中内容的父节点\n     */\n    _p.__getSelectNode = (function(){\n        var _checkNodeType = function(_node){\n            if (_node.nodeType == 1){\n                return _node;\n            }else{\n                _node = _node.parentNode;\n                return _checkNodeType(_node);\n            }\n        };\n        return function(_document){\n            var _range = this.__getRange(_document),\n                _node = _range.commonAncestorContainer||_range.parentElement();\n            if (!_range || !_node) return '';\n            return _checkNodeType(_node);\n        };\n    })();\n    /**\n     * 保存当前选择状态\n     * @param  {Node} _node 节点\n     * @return {Range}      范围\n     */\n    _p.__saveRange = function(_node){\n        // do nothing\n    };\n    /**\n     * 聚焦至选中区域\n     * @param  {Node} _node 节点\n     * @return {Void}\n     */\n    _p.__focusRange = function(_node){\n        _node.focus();\n    };\n    /**\n     * 清除选择状态\n     * @param  {Node} _node 节点\n     * @return {Void}\n     */\n    _p.__clearRange = function(_node){\n        // do nothing\n    };\n    /**\n     * FF支持selectionchange\n     * @param  {[type]} _document [description]\n     * @return {[type]}           [description]\n     */\n    _p.__supportSelectionChange = function(_document){\n        // do nothing\n    };\n    /**\n     * 移动光标至节点的指定位置\n     * @param  {Node}   _node     节点\n     * @param  {Number} _position 位置，0-末尾、1-起始\n     * @return {Void}\n     */\n    _p.__moveCursorPosition = (function(){\n        var _fmap = [function(_node){return _node.childNodes.length;}\n                    ,function(){return 0;}];\n        return function(_node,_position){\n            var _func = _fmap[_position];\n            if (!_func){\n                return;\n            }\n            _p.__getSelection(_p.__getWindow(_node))\n            .collapse(_node,_func(_node));\n        };\n    })();\n    /**\n     * 执行编辑命令\n     * @param  {Node}   _document 文档对象\n     * @param  {String} _command  命令名称\n     * @param  {String} _value    命令值\n     * @return {Void}\n     */\n    _p.__execCommand = function(_document,_command,_value){\n        if(_command == 'inserthtml'){\n            this.__insertHtml(_document,_value);\n            return;\n        }\n        _document.execCommand(_command,!1,_value);\n    };\n\n    /**\n     * 插入html命令处理\n     * @param {Object} _document 文档对象\n     * @param {Object} _html\n     */\n    _p.__insertHtml = function(_document,_html){\n        if (!document.selection){\n            _document.execCommand('inserthtml',!1,_html);\n            return;\n        }\n        var _range = _document.selection.createRange();\n        if (!!_range.pasteHTML){_range.pasteHTML(_html);return;}\n        _document.execCommand('delete',!1,null);\n        _document.selection.createRange().pasteHTML(_html);\n    };\n\n    /**\n     * 内容初步过滤\n     * @param {Object} _html\n     */\n    _p.__filterContent = function(_html,_keepClass){\n        var _filterHTML;\n        if (_keepClass){\n            _filterHTML = (_html||'').replace(__empty,'').replace(__reg_ccm,'');\n        }else{\n            _filterHTML = (_html||'').replace(__empty,'').replace(__reg_cls0,'').replace(__reg_cls1,'').replace(__reg_cls2,'').replace(__reg_ccm,'');\n        }\n        _filterHTML = !_p.__filterContentPath?_filterHTML:_p.__filterContentPath(_filterHTML);\n        return _filterHTML;\n    };\n\n    /**\n     * 过滤除了background-color以外的所有样式\n     * @param  {[type]} _html [description]\n     * @return {[type]}       [description]\n     */\n    _p.__filterContentStyle = (function(){\n        var _regMap = { 0:/(?:<[^>]* style)=\"([^\"]*)\"/gi,\n                        1:/(?:<[^>]* style)='([^']*)'/gi,\n                        2:/(?:<[^>]* style)=([^>\\s]*)/gi};\n        var _doFilter = function(_reg,_html){\n            _html = _html.replace(_regMap[_reg],function(_a,_b,_c){\n                var _prefix = _a.split('style')[0];\n                if(_b.match(__reg_bgc)!=null){\n                    var _str0 = '';\n                    var _bgc = _b.replace(__reg_bgc,function(_str,_sstr,_index){\n                        return _str0 += _str;\n                    }._$bind(this));\n\n                    return _prefix + ' style=\"' + _str0 + '\"';\n                }else{\n                    return _prefix;\n                }\n            }._$bind(this));\n            return _html;\n        };\n        return function(_html){\n            // IE多种情况同时出现\n            _html = _doFilter(0,_html);\n            _html = _doFilter(1,_html);\n            _html = _doFilter(2,_html);\n            return _html;\n        };\n    })();\n\n    return _p;\n});"
  },
  {
    "path": "src/util/editor/platform/editor.patch.js",
    "content": "NEJ.define([\n    'base/platform',\n\t'base/element',\n    'base/event',\n\t'base/util',\n\t'./editor.js'\n],function(_m,_e,_v,_u,_h,_p,_o,_f,_r){\n\t// webkit editor patch\n\tNEJ.patch('WV',function(){\n\t    var __reg_nwrd = /<\\/?[\\w]+:[\\w]+.*?>/gi;\n\t    /**\n\t     * 验证webkit下内容是否来自Word\n\t     * @param  {String} _html 内容\n\t     * @return {Boolean}      FF下内容是否来自Word\n\t     */\n\t    var __isFromWord = function(_html){\n\t        return (_html||'').search('</?[\\\\w]+:[\\\\w]+.*?>')>=0;\n\t    };\n\n\t    /**\n\t     * webkit清除word过来的冗余内容\n\t     * @param  {String} _html 内容\n\t     * @return {String} 过滤后的内容\n\t     */\n\t    _h.__filterWordContent = function(_html){\n\t        if(!__isFromWord(_html))\n\t            return _html;\n\t        return _html.replace(__reg_nwrd,'');\n\t    };\n\t});\n\n\t// gecko editor patch\n\tNEJ.patch('GV',function(){\n\t    /**\n\t     * 基本内容过滤\n\t     */\n\t    var __empty    = /(?:<(p|div)>(?:\\&nbsp\\;|<br\\/?>)<\\/\\1>|<br\\/?>|\\&nbsp\\;|\\s)+$/gi,\n\t        __reg_flnh = /\\f/g,//换页符\n\t        __reg_flns = /\\n|\\r/g,//换行符或回车符\n\t        __reg_fzag = /<(style|script).*?>.*?<\\/\\1>/gi,//style和script标签\n\t        __reg_ftag = /<\\/?(?:meta|link|!--\\[.+?\\]--|[\\w]+:[\\w]+).*?>/gi,\n\t        __reg_fimg = /<img(\\n|\\r|\\s|[^>])*?src=\"data:image\\/png;base64[^>]*?>/gi;//FF需要干掉base64的图片数据\n\t    /**\n\t     * 验证gecko下内容是否来自Word\n\t     * @param  {String}  _html 内容\n\t     * @return {Boolean} gecko下内容是否来自Word\n\t     */\n\t    var __isFromWord = function(_html){\n\t        return (_html||'').indexOf('<w:WordDocument>')>=0;\n\t    };\n\n\t    /**\n\t     * gecko清除word过来的冗余内容\n\t     * @param  {String} _html 内容\n\t     * @return {String} 过滤后的内容\n\t     */\n\t    _h.__filterWordContent = function(_html){\n\t        if(!__isFromWord(_html))\n\t            return _html;\n\t        return _html.replace(__reg_flns,'\\f')\n\t                    .replace(__reg_ftag,'')\n\t                    .replace(__reg_fzag,'')\n\t                    .replace(__reg_flnh,'\\n')\n\t                    .replace(__reg_fimg,'')\n\t                    .replace(__empty,'');\n\t    };\n\n\t    /**\n\t     * gecko特殊过滤\n\t     * @param {Object} _html\n\t     */\n\t    _h.__filterContentPath = function(_html){\n\t        _html = _html.replace(__reg_fimg,'');//过滤掉源数据是base64内容的图片\n\t        return _html;\n\t    };\n\n        /**\n         * 插入html命令处理\n         * @param {Object} _document 文档对象\n         * @param {Object} _html\n         */\n        _h.__insertHtml = function(_doc,_html){\n            // inserthtml for gecko\n            var _win = _h.__getWindow(_doc),\n                _range = _h.__getRange(_win);\n            var _node = _doc.createElement('div');\n            _node.innerHTML = _html;\n            // insert content\n            _range.deleteContents();\n            _u._$reverseEach(\n                _node.childNodes,\n                function(_elm){\n                    _range.insertNode(_elm);\n                }\n            );\n            // set focus\n            var _selection = _h.__getSelection(_win);\n            _selection.collapseToEnd();\n            _win.focus();\n        };\n\n        /**\n         * FF模拟selectionChange\n         * @param {Object} _document 文档对象\n         */\n        _h.__supportSelectionChange = (function(){\n            var MAC = /^Mac/.test(navigator.platform),\n                MAC_MOVE_KEYS = [65, 66, 69, 70, 78, 80],\n                SELECT_ALL_MODIFIER = MAC ? 'metaKey' : 'ctrlKey',\n                RANGE_PROPS = ['startContainer', 'startOffset', 'endContainer', 'endOffset'],\n                HAS_OWN_SELECTION = {INPUT: 1, TEXTAREA: 1},\n                _ranges;\n            /**\n             * 判断是否有WeakMap\n             */\n            var _newWeakMap = function(){\n                if (typeof WeakMap !== 'undefined') {\n                    return new WeakMap();\n                } else {\n                    return null;\n                }\n            };\n            /**\n             * 闭合光标\n             * @param {Object} _document 文档对象\n             */\n            var _getSelectionRange = function(_document){\n                var _selection = _h.__getSelection(_h.__getWindow(_document));\n                return _selection.rangeCount ? _selection.getRangeAt(0) : null;\n            };\n            /**\n             * input事件\n             * @param  {Event} _event 事件对象\n             */\n            var _onInput = function(_event){\n                if (!HAS_OWN_SELECTION[_event.target.tagName]) {\n                    _dispatchIfChanged(this, true);\n                }\n            };\n            /**\n             * keydown事件\n             * @param  {Event} _event 事件对象\n             */\n            var _onKeyDown = function(_event){\n                var _code = _event.keyCode;\n                if (_code === 65 && _event[SELECT_ALL_MODIFIER] && !_event.shiftKey && !_event.altKey || // Ctrl-A or Cmd-A\n                    _code >= 37 && _code <= 40 || // arrow key\n                    _event.ctrlKey && MAC && MAC_MOVE_KEYS.indexOf(_code) >= 0) {\n                  if (!HAS_OWN_SELECTION[_event.target.tagName]) {\n                    setTimeout(_dispatchIfChanged.bind(null, this), 0);\n                  }\n                }\n            };\n            /**\n             * mousedown事件\n             * @param  {Event} _event 事件对象\n             */\n            var _onMouseDown = function(_event){\n                if (_event.button === 0) {\n                    _v._$addEvent(this,'mousemove',_onMouseMove);\n                    setTimeout(_dispatchIfChanged.bind(null, this), 0);\n                }\n            };\n            /**\n             * mousemove事件\n             * @param  {Event} _event 事件对象\n             */\n            var _onMouseMove = function(_event){\n                if (_event.buttons & 1) {\n                    _dispatchIfChanged(this);\n                } else {\n                    _v._$delEvent(this, 'mousemove', _onMouseMove);\n                }\n            };\n            /**\n             * mouseup事件\n             * @param  {Event} _event 事件对象\n             */\n            var _onMouseUp = function(_event){\n                if (_event.button === 0) {\n                    setTimeout(_dispatchIfChanged.bind(null, this), 0);\n                } else {\n                    _v._$delEvent(this, 'mousemove', _onMouseMove);\n                }\n            };\n            /**\n             * focus事件\n             */\n            var _onFocus = function(){\n                setTimeout(_dispatchIfChanged.bind(null, this.document), 0);\n            };\n            /**\n             * 触发selectionchange\n             * @param {Object} _document 文档对象\n             * @param  {Event} _event 事件对象\n             */\n            var _dispatchIfChanged = function(_document,_force){\n                var _r = _getSelectionRange(_document);\n                if (_force || !_sameRange(_r, _ranges.get(_document))) {\n                    _ranges.set(_document, _r);\n                    setTimeout(function(){\n                        console.log('selectionchange')\n                        _v._$dispatchEvent(_document,'selectionchange');\n                    }, 0);\n                }\n            };\n            /**\n             * 判断光标是否相同\n             * @param  {Range} r1 光标对象\n             * @param  {Range} r2 光标对象\n             */\n            var _sameRange = function(_r1,_r2){\n                return _r1 === _r2 || _r1 && _r2 && RANGE_PROPS.every(function (_prop) {\n                    return _r1[_prop] === _r2[_prop];\n                });\n            }\n            /**\n             * 是否支持selectionchange\n             * @param {Object} _document 文档对象\n             */\n            var _hasNativeSupport = function(_document){\n                var _osc = _document.onselectionchange;\n                if (_osc !== undefined) {\n                    try {\n                        _document.onselectionchange = 0;\n                        return _document.onselectionchange === null;\n                    } catch (e) {\n                    } finally {\n                        _document.onselectionchange = _osc;\n                    }\n                }\n                return false;\n            };\n            return function(_document){\n                var _d = _document || document;\n                if (_ranges || !_hasNativeSupport(_d) && (_ranges = _newWeakMap())){\n                    if (!_ranges.has(_d)) {\n                        _ranges.set(_d, _getSelectionRange(_d));\n                        _v._$addEvent(_d,'input',_onInput);\n                        _v._$addEvent(_d,'keydown',_onKeyDown);\n                        _v._$addEvent(_d,'mousedown',_onMouseDown);\n                        _v._$addEvent(_d,'mousemove',_onMouseMove);\n                        _v._$addEvent(_d,'mouseup',_onMouseUp);\n                        _v._$addEvent(_d.defaultView,'focus',_onFocus);\n                    }\n                }\n            }\n        })();\n\t});\n\n\t// ie6-9 editor patch\n\tNEJ.patch('PV',function(){\n\t    var __reg_nwrd = /<\\/?[\\w]+:[\\w]+.*?>/gi,\n\t        __opspc    = '';\n\t    /**\n\t     * 执行编辑命令\n\t     * @param  {Node}   _document 文档对象\n\t     * @param  {String} _command  命令名称\n\t     * @param  {String} _value    命令值\n\t     * @return {Void}\n\t     */\n\t    _h.__execCommand =\n\t    _h.__execCommand._$aop(function(_event){\n\t        var _args = _event.args;\n\t        if (_args[1]=='hiliteColor')\n\t            _args[1] = 'backColor';\n\t    });\n\n\t    /**\n\t     * 验证presto下内容是否来自Word\n\t     * @param  {String} _html 内容\n\t     * @return {Boolean}      presto下内容是否来自Word\n\t     */\n\t    var __isFromWord = function(_html){\n\t        return (_html||'').search('</?[\\\\w]+:[\\\\w]+.*?>')>=0;\n\t    };\n\n\t    /**\n\t     * presto清除word过来的冗余内容\n\t     * @param  {String} _html 内容\n\t     * @return {String} 过滤后的内容\n\t     */\n\t    _h.__filterWordContent = function(_html){\n\t        if(!__isFromWord(_html))\n\t            return _html;\n\t        return _html.replace(__reg_nwrd,'');\n\t    };\n\n\t    /**\n\t     * presto特殊过滤\n\t     * @param {Object} _html\n\t     */\n\t    _h.__filterContentPath = function(_html){\n\t        return _html.replace(__opspc,'&nbsp;');\n\t    };\n\t});\n\n\t// ie editor patch\n\tNEJ.patch('TR',function(){\n\t     var __reg_nwrd = /<\\/?[\\w]+:[\\w]+.*?>/gi,\n\t         __reg_cxml = /<\\?xml[^>]*>/gi;\n\t    /**\n\t     * 验证trident下内容是否来自Word\n\t     * @param  {String} _html 内容\n\t     * @return {Boolean}      trident下内容是否来自Word\n\t     */\n\t    var __isFromWord = function(_html){\n\t        return (_html||'').search('</?[\\\\w]+:[\\\\w]+.*?>')>=0;\n\t    };\n\n\t    /**\n\t     * trident清除word过来的冗余内容\n\t     * @param  {String} _html 内容\n\t     * @return {String} 过滤后的内容\n\t     */\n\t    _h.__filterWordContent = function(_html){\n\t        if(!__isFromWord(_html))\n\t            return _html;\n\t        return _html.replace(__reg_nwrd,'').replace(__reg_cxml,'');\n\t    };\n\t});\n\n\t// ie6-8\n\tNEJ.patch('TR<=4.0',function(){\n        _h.__getSelectText = function(_document){\n            var _range = _h.__getRange(_document);\n            if (!_range) return '';\n            return _range.text;\n        };\n        _h.__getSelectHtml = function(_document){\n            var _range = _h.__getRange(_document);\n\t        if (!_range) return '';\n\t        var _html = _range.htmlText;\n            return _html||'';\n        };\n    });\n\n\t// ie6-8 editor patch\n\tNEJ.patch('TR<=4.0',function(){\n\t    /**\n\t     * 移动光标至节点的指定位置\n\t     * @param  {Node}   _node     节点\n\t     * @param  {Number} _position 位置，0-末尾、1-起始\n\t     * @return {Void}\n\t     */\n\t    _h.__moveCursorPosition = (function(){\n\t        var _fmap = [function(_node){return _node.innerText.length;}\n\t                    ,function(){return 0;}];\n\t        return _h.__moveCursorPosition._$aop(\n\t               function(_event){\n\t                    var _args = _event.args,\n\t                       _range = _h.__getRange(\n\t                                _h.__getWindow(_args[0]));\n\t                    if (!!_range && !!_range.move){\n\t                       _event.stopped = !0;\n\t                       var _func = _fmap[_args[1]];\n\t                       if (!_func) return;\n\t                       _range.move('character',_func(_args[0]));\n\t                       _range.select();\n\t                   }\n\t               });\n\t    })();\n\t});\n\n\t// ie10+ editor patch\n\tNEJ.patch('TR>=6.0',['./editor.td.js'],function(){\n\t    var _  = NEJ.P,\n\t        _u = _('nej.u'),\n\t        _p = _('nej.p'),\n\t        _h = _('nej.h');\n\t    var __reg_nwrd = /<\\/?[\\w]+:[\\w]+.*?>/gi;\n\t    /**\n\t     * 验证trident1下内容是否来自Word\n\t     * @param  {String} _html 内容\n\t     * @return {Boolean}      FF下内容是否来自Word\n\t     */\n\t    var __isFromWord = function(_html){\n\t        return (_html||'').search('</?[\\\\w]+:[\\\\w]+.*?>')>=0;\n\t    };\n\n\t    /**\n\t     * trident1清除word过来的冗余内容\n\t     * @param  {String} _html 内容\n\t     * @return {String} 过滤后的内容\n\t     */\n\t    _h.__filterWordContent = function(_html){\n\t        if(!__isFromWord(_html))\n\t            return _html;\n\t        return _html.replace(__reg_nwrd,'');\n\t    };\n\t});\n\t // ie7-10\n\tNEJ.patch('TR>=3.0',function(){\n\n        var  _rcache = {};\n        /**\n         * 执行编辑命令\n         * @param  {Node}   _document 文档对象\n         * @param  {String} _command  命令名称\n         * @param  {String} _value    命令值\n         * @return {Void}\n         */\n        _h.__execCommand =\n        _h.__execCommand._$aop(function(_event){\n            var _args = _event.args;\n            if (_args[1]=='styleWithCSS'){\n                _event.stopped = !0;\n                return;\n            }\n            _h.__focusRange(_args[0].body);\n            if (_args[1]=='hiliteColor')\n                _args[1] = 'backColor';\n        });\n        /**\n         * 保存当前选择状态\n         * @param  {Node} _node 节点\n         * @return {Void}\n         */\n        _h.__saveRange =\n        _h.__saveRange._$aop(function(_event){\n            if (!!document.selection){\n                _event.stopped = !0;\n                var _node = _event.args[0],\n                    _doc = _h.__getDocument(_node),\n                    _id = _e._$id(_doc);\n                _rcache[_id] = _h.__getRange(\n                    _h.__getWindow(_doc)\n                );\n            }\n        });\n        /**\n         * 聚焦至选中区域\n         * @param  {Node} _node 节点\n         * @return {Void}\n         */\n        _h.__focusRange =\n        _h.__focusRange._$aop(null,function(_event){\n            var _doc = _h.__getDocument(_event.args[0]),\n                _id = _e._$id(_doc),\n                _range = _rcache[_id];\n            if (!!_range){\n                if (!!_range.select){\n                    _range.select();\n                }else{\n                    // for ie11\n                    var _selection = _h.__getSelection(\n                        _h.__getWindow(_doc)\n                    );\n                    _selection.addRange(_range);\n                }\n                delete _rcache[_id];\n            }\n        });\n        /**\n         * 清除选择状态\n         * @param  {Node} _node 节点\n         * @return {Void}\n         */\n        _h.__clearRange =\n        _h.__clearRange._$aop(null,function(_event){\n            var _id = _e._$id(\n                _h.__getDocument(_event.args[0])\n            );\n            delete _rcache[_id];\n        });\n\n        /**\n         * 获取range cache\n         * @return {Object} range cache对象\n         */\n        _h.__getRcache = function(){\n            return _rcache;\n        };\n\n\t});\n\n\t// ie9+\n\tNEJ.patch('TR>=5.0',function(){\n\t    /**\n\t     * 保存当前选择状态\n\t     * @param  {Node} _node 节点\n\t     * @return {Void}\n\t     */\n\t    _h.__saveRange =\n\t    _h.__saveRange._$aop(function(_event){\n\t    \t// if have selection patched is on editor.td.js\n\t        if (!document.selection){\n\t            _event.stopped = !0;\n\t            var _node = _event.args[0],\n\t                _doc = _h.__getDocument(_node),\n\t                _id = _e._$id(_doc),\n\t                _rcache = _h.__getRcache();\n\t            _rcache[_id] = _h.__getRange(\n\t                _h.__getWindow(_doc)\n\t            );\n\t        }\n\t    });\n\t\t/**\n\t     * 插入html命令处理\n\t     * @param {Object} _document 文档对象\n\t     * @param {Object} _html\n\t     */\n\t    _h.__insertHtml = function(_doc,_html){\n\t        // inserthtml for ie11\n            var _win = _h.__getWindow(_doc),\n                _range = _h.__getRange(_win);\n            var _node = _doc.createElement('div');\n            _node.innerHTML = _html;\n            // insert content\n            _range.deleteContents();\n            _u._$reverseEach(\n                _node.childNodes,\n                function(_elm){\n                    _range.insertNode(_elm);\n                }\n            );\n            // set focus\n            var _selection = _h.__getSelection(_win);\n            _selection.collapseToEnd();\n            _win.focus();\n\t    };\n\n        /**\n         * 移动光标至节点的指定位置\n         * @param  {Node}   _node     节点\n         * @param  {Number} _position 位置，0-末尾、1-起始、3-当前位置\n         * @return {Void}\n         */\n        _h.__moveCursorPosition = (function(){\n            var _fmap = [function(_node){return _node.innerText.length;}\n                        ,function(){return 0;}];\n            return _h.__moveCursorPosition._$aop(\n                function(_event){\n                    var _args = _event.args,\n                        _node = _args[0],\n                        _position = _args[1],\n                        _func = _fmap[_position],\n                        _selection = _h.__getSelection(_h.__getWindow(_node));\n                    if (_position == 2){\n                        return;\n                    }\n                    if (_position == 3){\n                        var _focusOffset = _selection.focusOffset;\n                        _node = _selection.focusNode||_node;\n                        _selection.collapse(_node,_focusOffset);\n                    }else{\n                        _selection.collapse(_node,_func(_node));\n                    }\n                    _event.stopped = !0;\n                });\n        })();\n\t});\n\n    return _h;\n});\n"
  },
  {
    "path": "src/util/editor/platform/editor.td.js",
    "content": "/**\n * ------------------------------------------\n * 富文本编辑器接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/element',\n    './editor.js'\n],function(_e,_h,_p,_o,_f,_r){\n    \n    return _h;\n});\n"
  },
  {
    "path": "src/util/editor/platform/text.js",
    "content": "/**\n * ------------------------------------------\n * ı༭ӿʵļ\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/util'\n],function(u,p){\n    /**\n     * ͼƬб\n     * @param datatrans\n     * @private\n     */\n    p.__dumpImages = function(board){\n        var ret = [];\n        u._$forEach(board.items,function(it){\n            if (it.kind==='file'&&\n                it.type.indexOf('image')>-1){\n                ret.push(it.getAsFile());\n            }\n        });\n        return ret;\n    };\n\n\n});\n\n\n"
  },
  {
    "path": "src/util/editor/text.html",
    "content": "<head>\n    <style>\n        html,body{cursor:text;font-size:14px;font-family:Arial;word-wrap:break-word;height:100%;}\n        html,body,p{margin:0;padding:0;border:0}\n        html{overflow:hidden;}\n        body{overflow:auto;white-space:pre-wrap;}\n        ${css}\n    </style>\n</head>\n<body contenteditable=\"true\"></body>"
  },
  {
    "path": "src/util/editor/text.js",
    "content": "/*\n * ------------------------------------------\n * 富文本模拟纯文本编辑器封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/editor/text */\nNEJ.define([\n    'base/klass',\n    'base/element',\n    'util/event',\n    'util/template/jst',\n    'text!./text.html'\n],function(k,e,t,l,html,p,pro){\n    // cache jst\n    var sn = l._$add(html);\n\n    /**\n     * 富文本模拟纯文本编辑器\n     *\n     * @class     module:util/editor/text._$$Editor\n     * @extends   module:util/event._$$EventTarget\n     * @param     {Object}               arg0   - 可选配置参数\n     * @property  {String|Node|Function} parent - 控件所在容器节点或者追加控件节点执行函数\n     * @property  {String}               css    - 编辑内容样式\n     * @property  {String}               height - 高度设置，\n     */\n    p._$$Editor = k._$klass();\n    pro = p._$$Editor._$extend(t._$$EventTarget);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:util/editor/text._$$Editor#__init\n     * @return {Void}\n     */\n    pro.__init = function(options){\n        this.__sopt = {};\n        this.__fopt = {\n            visible:!0,\n            onload:this.__onIFrameLoaded._$bind(this)\n        };\n        this.__super(options);\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/editor/text._$$Editor#__reset\n     * @return {Void}\n     */\n    pro.__reset = function(options){\n        this.__super(options);\n        this.__sopt.css = options.css||'';\n        this.__fopt.parent = e._$get(options.parent);\n        this.__body = e._$createXFrame(this.__fopt);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/editor/text._$$Editor#__destroy\n     * @return {Void}\n     */\n    pro.__destroy = function(){\n        this.__super();\n        this._$setContent('');\n        delete this.__body;\n    };\n    /**\n     * 取编辑器节点\n     *\n     * @protected\n     * @method module:util/editor/text._$$Editor#__getBody\n     * @return {Void}\n     */\n    pro.__getBody = function(){\n        try{\n            return this.__body.contentWindow.document.body;\n        }catch(ex){\n            // ignore\n        }\n    };\n    /**\n     * 初始化输入区域\n     *\n     * @protected\n     * @method module:util/editor/text._$$Editor#__doInitTextArea\n     * @return {Void}\n     */\n    pro.__onIFrameLoaded = function(){\n        // init content\n        var doc = this.__body.contentWindow.document;\n        doc.open();\n        doc.write(l._$get(sn,this.__sopt));\n        doc.close();\n        // init event\n        this.__doInitDomEvent([[\n            doc,'paste',\n            this.__onContentPaste._$bind(this)\n        ],[\n            doc,'beforepaste',\n            this.__onBeforeContentPaste._$bind(this)\n        ],[\n            doc,'drop',\n            this.__onContentPaste._$bind(this)\n        ],[\n            doc,'keydown',\n            this.__doCheckEnter._$bind(this)\n        ]]);\n    };\n    /**\n     * 检查回车\n     *\n     * @protected\n     * @method module:util/editor/text._$$Editor#__doCheckEnter\n     * @return {Void}\n     */\n    pro.__doCheckEnter = function(event){\n        if (event.keyCode!=13){\n            return;\n        }\n        var options = {\n            ctrl:event.ctrlKey,\n            event:event\n        };\n        this._$dispatchEvent('onenter',options);\n        if (options.newline&&!!options.ctrl){\n            // TODO insert new line\n        }\n    };\n    /**\n     * 检查黏贴内容\n     *\n     * @protected\n     * @method module:util/editor/text._$$Editor#__doCheckContentPaste\n     * @return {Void}\n     */\n    pro.__doCheckContentPaste = function(){\n        this._$setContent(\n            this._$getContent()\n        );\n    };\n    /**\n     * 拖拽内容事件\n     *\n     * @protected\n     * @method module:util/editor/text._$$Editor#__onContentDrop\n     * @return {Void}\n     */\n    pro.__onContentDrop = function(event){\n        \n    };\n    /**\n     * 黏贴内容之前事件\n     *\n     * @protected\n     * @method module:util/editor/text._$$Editor#__onBeforeContentPaste\n     * @return {Void}\n     */\n    pro.__onBeforeContentPaste = function(event){\n        console.log(event);\n    };\n    /**\n     * 黏贴内容事件\n     *\n     * @protected\n     * @method module:util/editor/text._$$Editor#__onContentPaste\n     * @return {Void}\n     */\n    pro.__onContentPaste = function(event){\n        // TODO dump image\n        console.log(event);\n        // remove tags\n        //window.setTimeout(\n        //    this.__doCheckContentPaste._$bind(this),15\n        //);\n    };\n    /**\n     * 设置内容\n     *\n     * @method module:util/editor/text._$$Editor#_$setContent\n     * @param  {String} content - 内容\n     * @return {Void}\n     */\n    pro._$setContent = function(content){\n        var body = this.__getBody();\n        if (!body){\n            // TODO cache content\n            return;\n        }\n        if ('innerText' in body){\n            body.innerText = content||'';\n        }else{\n            body.textContent = content||'';\n        }\n    };\n    /**\n     * 取内容\n     *\n     * @method module:util/editor/text._$$Editor#_$getContent\n     * @return {String} 内容\n     */\n    pro._$getContent = function(){\n        var body = this.__getBody();\n        if (!!body){\n            return body.innerText||body.textContent;\n        }\n        return '';\n    };\n    /**\n     * 取滚动高度\n     *\n     * @method module:util/editor/text._$$Editor#_$getScrollHeight\n     * @return {Number} 滚动高度\n     */\n    pro._$getScrollHeight = function(){\n        var body = this.__getBody();\n        if (!!body){\n            return body.scrollHeight;\n        }\n        return 0;\n    };\n});\n\n\n"
  },
  {
    "path": "src/util/editor/toolbar.js",
    "content": "/*\n * ------------------------------------------\n * 富媒体编辑器工具栏封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/editor/toolbar */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'base/util',\n    'util/event'\n],function(NEJ,_k,_e,_v,_u,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 富媒体编辑器工具栏封装，输入的命令节点需使用以下属性标识\n     *  - data-command    指定执行的命令，没有设置此属性将被忽略\n     *\n     * @class     module:util/editor/toolbar._$$EditorToolbar\n     * @extends   module:util/event._$$EventTarget\n     * @param     {Object} _options - 可选配置参数\n     * @property  {Array}  list     - 命令节点列表\n     * @property  {String} selected - 命令选中样式，默认为js-selected\n     * @property  {String} disabled - 命令禁用样式，默认为js-disabled\n     */\n    /**\n     * 命令执行回调\n     *\n     * @event    module:util/editor/toolbar._$$EditorToolbar#oncommand\n     * @param    {Object}   arg0 - 可选配置参数\n     * @property {String}   name - 命令名称\n     * @property {Node}     node - 被命令影响的节点\n     */\n    _p._$$EditorToolbar = _k._$klass();\n    _pro = _p._$$EditorToolbar._$extend(_t._$$EventTarget);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:util/editor/toolbar._$$EditorToolbar#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__command = {};\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/editor/toolbar._$$EditorToolbar#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__selected = _options.selected||'js-selected';\n        this.__disabled = _options.disabled||'js-disabled';\n        this._$addCommand(_options.list);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/editor/toolbar._$$EditorToolbar#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        this.__command = {};\n        delete this.__selected;\n        delete this.__disabled;\n    };\n    /**\n     * 执行命令\n     *\n     * @protected\n     * @method module:util/editor/toolbar._$$EditorToolbar#__onCommand\n     * @param  {String} arg0 - 命令名称\n     * @return {Void}\n     */\n    _pro.__onCommand = function(_command){\n        _v._$stopBubble(arguments[1]);\n        var _node = this.__command[_command];\n        this._$dispatchEvent('oncommand',{\n            name:_command\n           ,node:this.__command[_command]\n        });\n    };\n    /**\n     * 添加命令节点\n     *\n     * @method module:util/editor/toolbar._$$EditorToolbar#_$addCommand\n     * @param  {String|Node|Array} arg0 - 命令节点\n     * @return {Void}\n     */\n    _pro._$addCommand = function(_node){\n        if (!_u._$isArray(_node)){\n            var _command = _e._$dataset(_node,'command');\n            if (!_command) return;\n            this.__command[_command] = _e._$get(_node);\n            this.__doInitDomEvent([\n                [_node,'click',this.__onCommand._$bind(this,_command)]\n            ]);\n        }\n        _u._$forEach(_node,this._$addCommand,this);\n    };\n    /**\n     * 取需要同步选中状态的命令列表\n     *\n     * @method module:util/editor/toolbar._$$EditorToolbar#_$getCommandList\n     * @return {Array} 命令列表\n     */\n    _pro._$getCommandList = function(){\n        return this.__command;\n    };\n    /**\n     * 设置命令的选中状态\n     *\n     * @method module:util/editor/toolbar._$$EditorToolbar#_$select\n     * @param  {String}  arg0 - 命令名称\n     * @param  {Boolean} arg1 - 是否选中\n     * @return {Void}\n     */\n    _pro._$select = function(_command,_selected){\n        var _node = this.__command[_command];\n        if (!_node) return;\n        !_selected ? _e._$delClassName(_node,this.__selected)\n                   : _e._$addClassName(_node,this.__selected);\n    };\n    /**\n     * 设置命令的禁用状态\n     *\n     * @method module:util/editor/toolbar._$$EditorToolbar#_$disable\n     * @param  {String}  arg0 - 命令名称\n     * @param  {Boolean} arg1 - 是否禁用\n     * @return {Void}\n     */\n    _pro._$disable = function(_command,_disabled,_class){\n        var _node = this.__command[_command];\n        if (!_node) return;\n        _e._$delClassName(_node,_class);\n        !_disabled ? _e._$delClassName(_node,this.__disabled)\n                   : _e._$addClassName(_node,this.__disabled);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/effect/api.js",
    "content": "/*\n * ------------------------------------------\n * 动画API实现文件\n * @version  1.0\n * @author   cheng-lin(cheng-lin@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/effect/api */\nNEJ.define([\n    'base/element',\n    'base/event',\n    'base/util',\n    '{platform}effect.api.js',\n    'util/effect/effect',\n    'base/chain'\n],function(_e,_v,_u,_h,_t0,_x,_p,_o,_f,_r) {\n    /**\n     * 初始化特效参数\n     *\n     * @protected\n     * @method module:util/effect/api#__initOptions\n     * @param  {Object} arg0 - 特效参数\n     * @return {Object} 特效参数\n     */\n    _p.__initOptions = function(_options){\n        _options = _options||{};\n        _options.onstop = _options.onstop||_f;\n        _options.onplaystate = _options.onplaystate||_f;\n        return _options;\n    };\n\n    /**\n     * 检查是否可以做动画\n     *\n     * @protected\n     * @method module:util/effect/api#__doBeforeStart\n     * @param  {Node}    node - 目标节点\n     * @param  {Object}  arg0 - 特殊属性对象\n     * @return {Boolean} 是否可以做动画\n     */\n    _p.__doBeforeStart = (function(){\n        // 如果有一个属性是没有变化的，此属性的回调不会发生，避免此情况\n        var _doCheckState = function(_node,_objs){\n            var _number,_flag=true;\n            _u._$forIn(_objs,function(_value,_name){\n                if (_name === 'opacity'){\n                    _number = _h.__formatNumber ? _h.__formatNumber(_node) : _e._$getStyle(_node,_name);\n                    _value = _h.__formatTo ? _h.__formatTo(_value) : _value;\n                }else{\n                    _number = _e._$getStyle(_node,_name);\n                }\n                // 属性没有变化是不允许的\n                if (parseInt(_number) === _value)\n                    _flag = false;\n            }._$bind(this));\n            return _flag;\n        };\n        return function(_node,_objs){\n            if (!_doCheckState(_node,_objs)) return !1;\n            return !0;\n        };\n    })();\n\n    /**\n     * 淡入淡出操作\n     *\n     * @protected\n     * @method   module:util/effect/api#__doFade\n     * @param    {String|Node} _node - 节点或者节点ID\n     *\n     * @param    {Object}   arg0     - 配置参数\n     * @property {String} opacity    - 目标透明度\n     * @property {String} timing     - 运动曲线\n     * @property {Number} delay      - 延迟时间\n     * @property {String} duration   - 运动时间\n     *\n     * @param  {Number}   arg1 - 1表示淡入，0表示淡出，优先使用前一个参数配置\n     * @return {Void}\n     */\n    _p.__doFade = (function(){\n        // 检查节点是否隐藏\n        var _doCheckDisplay = function(_node){\n            var _display = _e._$getStyle(_node,'display');\n            if (_display === 'none') return !1;\n            return !0;\n        };\n        return function(_node,_options,_default){\n            var _opacity = _options.opacity||_default;\n                   _node = _e._$get(_node);\n            // display is none\n            if (!_doCheckDisplay.call(_node)) return !1;\n            // isLocked\n            if (!!_node.effect) return !1;\n            // attribute not change\n            if (!_p.__doBeforeStart(_node,{opacity:_opacity})) return !1;\n            _options = _p.__initOptions(_options);\n            _node.effect = _t0._$$Effect._$allocate(\n                {\n                    node:_node,\n                    transition:[\n                        {\n                            property:'opacity',\n                            timing:_options.timing||'ease-in',\n                            delay:_options.delay||0,\n                            duration:_options.duration||1\n                        }\n                    ],\n                    styles:['opacity:'+_opacity],\n                    onstop:function(_state,_flag){\n                        _node.effect = _t0._$$Effect._$recycle(_node.effect);\n                        _options.onstop.call(null,_state,_flag);\n                    },\n                    onplaystate:_options.onplaystate._$bind(_node.effect)\n                }\n            );\n            _node.effect._$start();\n        };\n    }._$bind(this))();\n\n    /**\n     * 淡入动画\n     *\n     * 页面结构举例\n     * ```html\n     * // 必须有opacity属性\n     * <div id=\"box\" style=\"opact\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     * \t   'base/element',\n     *     'util/effect/api'\n     * ],function(_e,_t,_p,_o,_f,_r){\n     *     var _node = _e._$get(\"box\");\n     *     _t._$fadeIn(_node,{\n     *         // 注意两位小数可能没有预期效果\n     *         opacity:0.8,\n     *         timing:'ease-out',\n     *         delay:0,\n     *         duration:5\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/effect/api._$fadeIn\n     * @param    {Node|String} arg0 - 节点或者节点ID\n     *\n     * @param    {Object} arg1  - 配置参数\n     * @property {String} opacity  - 目标透明度\n     * @property {String} timing   - 运动曲线\n     * @property {Number} delay    - 延迟时间\n     * @property {String} duration - 运动时间\n     * @return   {Void}\n     */\n    /**\n     * @method CHAINABLE._$fadeIn\n     * @see module:util/effect/api._$fadeIn\n     */\n    _p._$fadeIn = function(_node,_options){\n        return _p.__doFade(_node,_options,1);\n    };\n\n    /**\n     * 淡出动画\n     *\n     * 页面结构举例\n     * ```html\n     * <div id=\"box\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     * \t   'base/element',\n     *     'util/effect/api'\n     * ],function(_e,_t,_p,_o,_f,_r){\n     *     var _node = _e._$get(\"box\");\n     *     _t._$fadeOut(_node,{\n     *         // 注意两位小数可能没有预期效果\n     *         opacity:0.8,\n     *         timing:'ease-out',\n     *         delay:0,\n     *         duration:5\n     *     });\n     * });\n     * ```\n     *\n     * @method    module:util/effect/api._$fadeOut\n     * @param  {Node|String} arg0 - 节点或者节点ID\n     *\n     * @param  {Object}   arg1 \t   - 配置参数\n     * @property {String} opacity  - 目标透明度\n     * @property {String} timing   - 运动曲线\n     * @property {Number} delay    - 延迟时间\n     * @property {String} duration - 运动时间\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$fadeOut\n     * @see module:util/effect/api._$fadeOut\n     */\n    _p._$fadeOut = function(_node,_options){\n        return _p.__doFade(_node,_options,0);\n    };\n\n    /**\n     * 终止淡入淡出特效\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     * \t   'base/element',\n     *     'util/effect/api'\n     * ],function(_e,_t,_p,_o,_f,_r){\n     *     var _node = _e._$get(\"box\");\n     *     _t._$fadeStop(_node);\n     * });\n     * ```\n     *\n     * @param  {Node|String} arg0 - 节点或者节点ID\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$fadeStop\n     * @see module:util/effect/api._$fadeStop\n     */\n    _p._$fadeStop = function(_node){\n        _p._$stopEffect(_node);\n    };\n\n    /**\n     * 中途停止特效，直接跑到最后的目标\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     * \t   'base/element',\n     *     'util/effect/api'\n     * ],function(_e,_t,_p,_o,_f,_r){\n     *     var _node = _e._$get(\"box\");\n     *     _t._$stopEffect(_node);\n     * });\n     * ```\n     *\n     * @param  {Node|String} arg0 - 节点或者节点ID\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$stopEffect\n     * @see module:util/effect/api._$stopEffect\n     */\n    _p._$stopEffect = function(_node){\n        _node = _e._$get(_node);\n        if (_node.effect && _node.effect._$stop(true)){\n            return;\n        }\n    };\n\n    /**\n     * 移动节点\n     *\n     * 页面结构举例\n     * ```html\n     * <div id=\"box\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     * \t   'base/element',\n     *     'util/effect/api'\n     * ],function(_e,_t,_p,_o,_f,_r){\n     *     var _node = _e._$get(\"box\");\n     *     // 需要配合预先定义的position属性\n     *     _t._$moveTo(_node,{top:100,left:100},{\n     *         timing:'ease-out',\n     *         delay:0,\n     *         duration:[5,1]\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/effect/api._$moveTo\n     * @param    {Node|String} arg0 - 节点或者节点ID\n     *\n     * @param    {Object} arg1 \t    - 配置参数\n     * @property {String} top       - 移动节点的top值\n     * @property {String} left      - 移动节点的left值\n     * @property {String} timing    - 运动曲线\n     * @property {Number} delay     - 延迟时间\n     * @property {String} duration  - 运动时间\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$moveTo\n     * @see module:util/effect/api._$moveTo\n     */\n    _p._$moveTo = function(_node,_position,_options){\n        _node = _e._$get(_node);\n        if (!!_node.effect) return !1;\n        if (!_p.__doBeforeStart(_node,_position)) return !1;\n        _options = _p.__initOptions(_options);\n        _options.duration = _options.duration||[];\n        var _top = _position.top||0,_left= _position.left||0;\n        _node.effect = _t0._$$Effect._$allocate(\n            {\n                node:_node,\n                transition:[\n                    {\n                        property:'top',\n                        timing:_options.timing||'ease-in',\n                        delay:_options.delay||0,\n                        duration:_options.duration[0]||1\n                    },\n                    {\n                        property:'left',\n                        timing:_options.timing||'ease-in',\n                        delay:_options.delay||0,\n                        duration:_options.duration[1]||1\n                    }\n                ],\n                styles:['top:'+_top,'left:'+_left],\n                onstop:function(_state,_flag){\n                    _node.effect = _t0._$$Effect._$recycle(_node.effect);\n                    _options.onstop.call(null,_state,_flag);\n                },\n                onplaystate:_options.onplaystate._$bind(_node.effect)\n            }\n        );\n        _node.effect._$start();\n    };\n\n    /**\n     * 移动节点\n     *\n     * 页面结构举例\n     * ```html\n     * <div id=\"box\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     * \t   'base/element',\n     *     'util/effect/api'\n     * ],function(_e,_t,_p,_o,_f,_r){\n     *     var _node = _e._$get(\"box\");\n     *     // 需要配合预先定义的position属性\n     *     // top,bottom,left,right只可操作其一\n     *     // 同时操作2个属性参照moveTo\n     *     _t._$slide(_node,'top:+100'{\n     *         timing:'ease-out',\n     *         delay:0,\n     *         duration:5\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/effect/api._$slide\n     * @param    {Node|String} arg0 - 节点或者节点ID\n     *\n     * @param    {String} arg1     - 滑动的方向\n     *\n     * @param    {Object} arg2     - 配置参数\n     * @property {String} timing   - 运动曲线\n     * @property {Number} delay    - 延迟时间\n     * @property {String} duration - 运动时间\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$slide\n     * @see module:util/effect/api._$slide\n     */\n    _p._$slide = function(_node,_position,_options){\n        _node = _e._$get(_node);\n        if (!!_node.effect) return !1;\n        _options = _p.__initOptions(_options);\n        var _list  = _position.split(':'),\n            _pro0  = _list[0],\n            _styles= [];\n        _styles.push(_position);\n        _node.effect = _t0._$$Effect._$allocate(\n            {\n                node:_node,\n                transition:[\n                    {\n                        property:_pro0,\n                        timing:_options.timing||'ease-in',\n                        delay:_options.delay||0,\n                        duration:_options.duration||1\n                    }\n                ],\n                styles:_styles,\n                onstop:function(_state,_flag){\n                    _node.effect = _t0._$$Effect._$recycle(_node.effect);\n                    _options.onstop.call(null,_state,_flag);\n                },\n                onplaystate:_options.onplaystate._$bind(_node.effect)\n            }\n        );\n        _node.effect._$start();\n    };\n\n    /**\n     * toggle效果\n     *\n     * 页面结构举例\n     * ```html\n     * // overflow:hidden;visibility:hidden;display:none;\n     * <div id=\"box\">123</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     * \t   'base/element',\n     *     'util/effect/api'\n     * ],function(_e,_t,_p,_o,_f,_r){\n     *     var _node = _e._$get(\"box\");\n     *     _t._$toggleEffect(_box,'height',{value:100,timing:'ease-out',duration:'1.2'});\n     * });\n     * ```\n     *\n     * @method   module:util/effect/api._$toggleEffect\n     * @param    {Node|String} arg0 - 节点或者节点ID\n     *\n     * @param    {String} arg1     - 需要改变的属性，height或width\n     *\n     * @param    {Object} arg2     - 配置参数\n     * @property {Number} value    - 属性值\n     * @property {String} timing   - 运动曲线\n     * @property {Number} delay    - 延迟时间\n     * @property {String} duration - 运动时间\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$toggleEffect\n     * @see module:util/effect/api._$toggleEffect\n     */\n    _p._$toggleEffect = (function(){\n        var _doCheck = function(_node,_type){\n            return _type == 'height' ? _node.clientHeight : _node.clientWidth;\n        };\n        return function(_node,_type,_options){\n            _node = _e._$get(_node);\n            if (!!_node.effect) return !1;\n            _options = _p.__initOptions(_options);\n            // set\n            var _value = _options.value||false;\n            if (!_value){\n                _e._$setStyle(_node,'display','block');\n                var _node = _e._$get(_node);\n                _value = _doCheck(_node,_type);\n            }\n            var _flag = _e._$getStyle(_node,'visibility');\n            if (_flag === 'hidden'){\n                _node.style.height = 0;\n                _e._$setStyle(_node,'visibility','inherit');\n                _node.effect = _t0._$$Effect._$allocate(\n                    {\n                        node:_node,\n                        transition:[\n                            {\n                                property:_type,\n                                timing:_options.timing||'ease-in',\n                                delay:_options.delay||0,\n                                duration:_options.duration||1\n                            }\n                        ],\n                        styles:[_type + ':' + _value],\n                        onstop:function(_state,_flag){\n                            _node.effect = _t0._$$Effect._$recycle(_node.effect);\n                            _options.onstop.call(null,_state,_flag);\n                            _sto = window.clearTimeout(_sto);\n                        },\n                        onplaystate:_options.onplaystate._$bind(_node.effect)\n                    }\n                );\n            }else{\n                _node.style.height = isNaN(_value) ? _value : _value+'px';\n                _node.effect = _t0._$$Effect._$allocate(\n                    {\n                        node:_node,\n                        transition:[\n                            {\n                                property:_type,\n                                timing:_options.timing||'ease-in',\n                                delay:_options.delay||0,\n                                duration:_options.duration||1\n                            }\n                        ],\n                        styles:[_type + ':' + 0],\n                        onstop:function(_state,_flag){\n                            _e._$setStyle(_node,'visibility','hidden');\n                            _e._$setStyle(_node,_type,'auto');\n                            _node.effect = _t0._$$Effect._$recycle(_node.effect);\n                            _options.onstop.call(null,_state,_flag);\n                            _sto = window.clearTimeout(_sto);\n                        },\n                        onplaystate:_options.onplaystate._$bind(_node.effect)\n                    }\n                );\n            }\n            var _sto = window.setTimeout(function(){_node.effect._$start();}._$bind(this),0);\n        };\n    })();\n    // for chainable method\n    _x._$merge(_p);\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.e'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/effect/effect.api.js",
    "content": "// link to util/effect/api for compatible\n// use util/effect/api for new project\nNEJ.define(['./api.js'],function(_t){return _t;});"
  },
  {
    "path": "src/util/effect/effect.js",
    "content": "/*\n * ------------------------------------------\n * 动画特效基类实现文件\n * @version  1.0\n * @author   cheng-lin(cheng-lin@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/effect/effect */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    '{platform}effect.js',\n    'base/element',\n    'base/util',\n    'util/event'\n],function(NEJ,_k,_h,_e,_u,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 动画特效基类\n     * 如果属性没有变化不能写入，此属性的回调不会发生\n     * 目前支持的css属性有：\n     * width,height,z-index,opacity,margin,padding,font-size,font-weight\n     * top,right,bottom,left(需要指定position)\n     * 高级浏览器支持color相关属性\n     * 属性单位限定px,不支持em或pt\n     *\n     * 页面结构举例\n     * ```html\n     * <div id='box' style='position:absolute;z-index:10;'>abc</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * var _effect = _p._$$Effect._$allocate(\n     *    {\n     *        node:'box',\n     *        transition:[\n     *            {\n     *                property:'top',\n     *                timing:'ease-in',\n     *                delay:1,\n     *                duration:10\n     *            },\n     *            {\n     *                property:'z-index',\n     *                timing:'ease-in',\n     *                delay:2,\n     *                duration:10\n     *            }\n     *        ],\n     *        styles:['top:+=460','z-index:999'],\n     *        onstop:function(){\n     *       },\n     *        onplaystate:function(){\n     *        }\n     *    }\n     * );\n     * // 所有动画统一轨迹和时间\n     * var _effect2 = _p._$$Effect._$allocate({\n     *        node:'box',\n     *        transition:[\n     *            {\n     *                property:'all',\n     *                timing:'ease-in',\n     *                delay:1,\n     *                duration:10\n     *            }\n     *        ],\n     *        styles:['top:+=460','z-index:999'],\n     *        onstop:function(){\n     *       },\n     *        onplaystate:function(){\n     *        }\n     * });\n     * ```\n     *\n     * @class     module:util/effect/effect._$$Effect\n     * @extends   module:util/event._$$EventTarget\n     * @param     {Object}      arg0       - 可选配置参数\n     * @property  {String|Node} node       - 动画节点\n     * @property  {Array}       transition - 动画属性列表\n     * |意义|属性    |延迟启动时间|持续时间|运动轨迹    |\n     * |:---|:---    |:---        |:---    |:---        |\n     * |属性|property|delay       |duration|timing      |\n     * |值  |width   |1           |10      |linear,ease-in,ease-out,ease-in-out|\n     * @property  {Array}      styles      - 动画需要改变的css属性\n     */\n    /**\n     * 动画停止的回调\n     *\n     * @event  module:util/effect/effect._$$Effect#onstop\n     * @return {Void}\n     */\n    /**\n     * 动画中间状态回调\n     *\n     * @event  module:util/effect/effect._$$Effect#onplaystate\n     * @return {Void}\n     */\n    _p._$$Effect = _k._$klass();\n    _pro = _p._$$Effect._$extend(_t._$$EventTarget);\n\n    /**\n     * 初始化方法\n     *\n     * @protected\n     * @method module:util/effect/effect._$$Effect#onstop#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__node   = _e._$get(_options.node);\n        this.__styles = _options.styles||[];\n        this.__onstop = _options.onstop||_f;\n        this.__transition = _options.transition||[];\n        this.__propMap = {};\n        this.__animRule= this.__doParseStyle();\n        this.__doInitDomEvent([\n            [this.__node,'transitionend',this.__onTransitionEnd._$bind(this)]\n        ]);\n    };\n\n    /**\n     * 销毁对象\n     *\n     * @protected\n     * @method module:util/effect/effect._$$Effect#onstop#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        if(!!this.__intvl){\n            this.__intvl = window.clearInterval(this.__intvl);\n        }\n        // 这里回收关于此节点的动画信息\n        delete this.__node;\n        delete this.__styles;\n        delete this.__animRule;\n        delete this.__propMap;\n        delete this.__lastProp;\n        delete this.__transition;\n        delete this.__intvl;\n        this.__super();\n    };\n\n    /**\n     * 监听动画结束事件\n     *\n     * @protected\n     * @method module:util/effect/effect._$$Effect#onstop#__onTransitionEnd\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTransitionEnd = function(_event){\n        if(!!this.__start&&this.__isLast(_event)){\n            this.__start = !1;\n            this._$stop();\n        }\n    };\n\n    /**\n     * 是否是最后结束的属性\n     *\n     * @protected\n     * @method module:util/effect/effect._$$Effect#onstop#__isLast\n     * @param  {Event} arg0 - 事件对象\n     * @return {Boolean}       是否是最后结束的属性\n     */\n    _pro.__isLast = function(_event){\n        var _name = _event.propertyName,\n            _flag = false;\n        _u._$forIn(this.__lastProp,function(_value){\n            _flag = _name.indexOf(_value) > -1;\n        }._$bind(this));\n        if(_flag || !!this.__lastProp[_name])\n            return !0;\n        else\n            return !1;\n    };\n    /**\n     * 解析出目标样式\n     *\n     * @protected\n     * @method module:util/effect/effect._$$Effect#onstop#__doParseStyle\n     * @return {String} 解析好的目标样式\n     */\n    _pro.__doParseStyle = (function(){\n        // 根据属性的拼写规则，做适当的调整\n        var _doParseStyle = function(_style){\n            var _list  = _style.split(':'),\n                _prop  = _list[0],\n                _value = _list[1],\n                _node  = this.__node;\n            // 需要解析=号\n            if(_value.indexOf('=') > -1){\n                var _a = parseInt(_e._$getStyle(_node,_prop))||0;\n                var _b = parseInt(_value.split('=')[1]);\n                if(_value.indexOf('+') > -1)\n                    _value = _a + _b;\n                else\n                    _value = _a - _b;\n            }\n            // 需要加单位\n            if(_h.__doCheckProp(_prop)){\n                if(_value.toString().indexOf('px') < 0)\n                    _value += 'px';\n            }\n            this.__propMap[_prop] = _value;\n        };\n        // 解析动画的规则\n        var _doParseAnim = function(_index){\n            if(!this.__transition[_index])\n                return '';\n            var _rule = this.__transition[_index],\n                _t = _rule.duration + _rule.delay;\n            if( _t > this.__sumtime){\n                this.__lastProp = {};\n                this.__sumtime = _t;\n                this.__lastProp[_rule.property] = _rule.property;\n            }else if(_t == this.__sumtime){\n                this.__lastProp[_rule.property] = _rule.property;\n            }\n            return _rule.property + ' ' + _rule.duration + 's ' + _rule.timing + ' ' + _rule.delay + 's,';\n        };\n        return function(){\n            var _animRule = '';\n            this.__sumtime = 0;\n            this.__lastProp = {}\n            _u._$forEach(this.__styles,function(_style,_index){\n                _doParseStyle.call(this,_style);\n                _animRule += _doParseAnim.call(this,_index);\n            }._$bind(this));\n            return _animRule;\n        };\n    })();\n\n    /**\n     * 动画开始后，监听节点的样式\n     *\n     * @protected\n     * @method module:util/effect/effect._$$Effect#onstop#__onPlayState\n     * @return {Void}\n     */\n    _pro.__onPlayState = function(){\n        this.__state = {};\n        _u._$forIn(this.__propMap,function(_value,_prop){\n            this.__state[_prop] = _e._$getStyle(this.__node,_prop);\n        }._$bind(this));\n        this._$dispatchEvent('onplaystate',this.__state);\n    };\n\n    /**\n     * 开始动画\n     *\n     * @protected\n     * @method module:util/effect/effect._$$Effect#onstop#_$start\n     * @return {Void}\n     */\n    _pro._$start = function(){\n        this.__start = !0;\n        _h.__onStart(this.__node,this.__propMap,this.__animRule,this.__onstop);\n        this.__intvl = window.setInterval(this.__onPlayState._$bind(this),49);\n    };\n\n    /**\n     * 取消动画\n     *\n     * @method module:util/effect/effect._$$Effect#_$stop\n     * @param  {Boolean} flag - 是否取消动画\n     * @return {Void}\n     */\n    _pro._$stop = function(_flag){\n        this.__intvl = window.clearInterval(this.__intvl);\n        _h.__onStop(this.__node,this.__propMap,this.__onstop,_flag);\n    };\n\n    /**\n     * 暂停动画\n     *\n     * @method module:util/effect/effect._$$Effect#_$paused\n     * @return {Void}\n     */\n    _pro._$paused = function(){\n       // todo\n    };\n\n    /**\n     * 暂停后重新开始动画\n     *\n     * @method module:util/effect/effect._$$Effect#_$restart\n     * @return {Void}\n     */\n    _pro._$restart = function(){\n        // todo\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/effect/platform/effect.api.js",
    "content": ""
  },
  {
    "path": "src/util/effect/platform/effect.api.patch.js",
    "content": "NEJ.define([\n    'base/element'\n],function(_e,_h,_o,_f,_r){\n    // ie8-\n    NEJ.patch('TR<=4.0',function(){\n        _h.__formatTo = function(_to){\n            return _to * 100;\n        };\n\n        _h.__formatNumber = function(_node){\n            var _filter = _e._$getStyle(_node,'filter');\n            // 没设置透明度默认为100\n            if(_filter === ''){\n                _e._$setStyle(_node,'filter','alpha(opacity=100)');\n                _number = 100;\n            }else{\n                _number = parseFloat(_filter.split('=')[1])||0;\n            }\n            return _number;\n        };\n    });\n\n    return _h;\n});"
  },
  {
    "path": "src/util/effect/platform/effect.js",
    "content": "/**\n * ------------------------------------------\n * 动画效果接口实现文件\n * @version  1.0\n * @author   cheng-lin(cheng-lin@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/global',\n    'base/element'\n],function(NEJ,_e,_p,_o,_f,_r){\n    var _suffix = {\n        'opacity':1,\n        'z-index':1,\n        'background':1,\n        'font-weight':1,\n        'filter':1\n    };\n    /**\n     * 检查属性是否需要加单位\n     * @param  {String}  属性\n     * @return {Boolean} true表示需要加单位，false表示不需要加单位\n     */\n    _p.__doCheckProp = function(_prop){\n        return (_suffix[_prop] === undefined) && (_prop.indexOf('color') < 0);\n    };\n    /**\n     * 执行动画\n     * @param  {Node}   动画节点\n     * @param  {String} 动画目标样式\n     * @param  {String} 动画变换信息\n     * @return {Void}\n     */\n    _p.__onStart = function(_node,_rules,_anim){\n        _anim = _anim.slice(0,-1);\n        _e._$setStyle(_node,'transition',_anim);\n        _e._$style(_node,_rules);\n    };\n\n    /**\n     * 取消动画\n     * @param  {Node}   动画节点\n     * @param  {String} 节点目标样式\n     * @return {Void}\n     */\n    _p.__onStop = function(_node,_state,_stop,_flag){\n        _e._$style(_node,_state);\n        _e._$setStyle(_node,'transition','none');\n        _stop.call(null,_state,_flag);\n    };\n\n    return _p;\n});"
  },
  {
    "path": "src/util/effect/platform/effect.patch.js",
    "content": "NEJ.define([\n\t'./effect.js',\n\t'base/element'\n],function(_h,_e,_p,_o,_f,_r){\n\t// ff effect patch\n\tNEJ.patch('GV',function(){\n\t    /**\n\t     * 执行动画\n\t     * @param  {Node}   动画节点\n\t     * @param  {String} 动画目标样式\n\t     * @param  {String} 动画变换信息\n\t     * @return {nej.h}\n\t     */\n\t    _h.__onStart = function(_node,_rules,_anim){\n\t        _anim = _anim.slice(0,-1);\n\t        _e._$setStyle(_node,'transition',_anim);\n\t        // FF toggle fix\n\t        setTimeout(function(){\n\t            _e._$style(_node,_rules);\n\t        },33);\n\t        return this;\n\t    };\n\t});\n\n\t// ie系列 effect patch\n\tNEJ.patch('TR<=5.0',['base/util',\n\t          \t\t\t 'util/animation/linear',\n\t\t\t\t\t\t 'util/animation/easein',\n\t\t\t\t\t\t 'util/animation/easeout',\n\t\t\t\t\t\t 'util/animation/easeinout'],\n\tfunction(_u,_t0,_t1,_t2,_t3){\n\t\tvar _animMap = {\n\t\t  'linear'     : _t0._$$AnimLinear,\n\t\t  'ease-in'    : _t1._$$AnimEaseIn,\n\t\t  'ease-out'   : _t2._$$AnimEaseOut,\n\t\t  'ease-in-out': _t3._$$AnimEaseInOut\n\t\t};\n\n\t\t/**\n\t\t * 执行动画\n\t\t * @param  {Node}   动画节点\n\t\t * @param  {Array}  动画目标样式:[{width:500px;},{height:500px;}]\n\t\t * @param  {String} 动画变换信息\n\t\t * @param  {Event}  动画停止的回调\n\t\t * @return {nej.h}\n\t\t */\n\t\t_h.__onStart = (function(){\n\t\t  // 属性是all的情况，重新构建anim\n\t\t  var _doRbAnim = function(_rules,_anim){\n\t\t    var _str = '';\n\t\t    _u._$forIn(_rules,function(_value,_name){\n\t\t      _str += _anim.replace('all',_name);\n\t\t    });\n\t\t    return _str;\n\t\t  };\n\t\t  // 适配特殊属性\n\t\t  var _doAdap  = function(_value,_prop){\n\t\t    if(_prop === 'filter'){\n\t\t      _value = _u._$fixed(_value,0);\n\t\t      _value = 'alpha(opacity=' + _value + ')';\n\t\t    }\n\t\t    if(_prop === 'z-index')\n\t\t      _value = _u._$fixed(_value,0);\n\t\t    return _value;\n\t\t  };\n\t\t  // 适配构造器\n\t\t  var _doFindCur = function(_value){\n\t\t    return _animMap[_value.split(' ')[2]];\n\t\t  };\n\t\t  // 解析参数\n\t\t  var _doParse = function(_node,_value,_rules,_stop,_index){\n\t\t    var _value= _value.split(' '),\n\t\t        _prop = _value[0],\n\t\t        _from = parseFloat(_e._$getStyle(_node,_prop))||0,\n\t\t        _to   = parseFloat(_rules[_prop])||0,\n\t\t        _cutr = _animMap[_value[2]],\n\t\t        _delay = _value[3].slice(0,-1) * 1000||0,\n\t\t        _durtReal = _value[1].slice(0,-1) * 1000||0,\n\t\t        _durt = _value[1].slice(0,-1) * 1000 + _value[3].slice(0,-1) * 1000;\n\t\t    if(_durt >= _node.sumTime){\n\t\t      _node.sumTime = _durt;\n\t\t      _node.isLastOne = _index;\n\t\t    }\n\t\t    if(_prop === 'opacity'){\n\t\t    \t_prop = _h.__formatOpacity ? _h.__formatOpacity():_prop;\n\t\t    \t_from = _h.__formatFrom ? _h.__formatFrom(_node):_from;\n\t\t    \t_to   = _h.__formatTo ? _h.__formatTo(_to):_to;\n\t\t    }\n\t\t    var _options = {\n\t\t        delay:_delay,\n\t\t        from:{\n\t\t            offset:_from\n\t\t        },\n\t\t        to:{\n\t\t            offset:_to\n\t\t        },\n\t\t        duration:_durtReal,\n\t\t        onupdate:function(_offset){\n\t\t          // if(_node.isStop) return;\n\t\t          var _value = _offset.offset;\n\t\t          if(!_h.__doCheckProp(_prop)){\n\t\t            _value = _doAdap(_value,_prop);\n\t\t                _e._$setStyle(_node,_prop,_value);\n\t\t            }else{\n\t\t                _e._$setStyle(_node,_prop,_value + 'px');\n\t\t            }\n\t\t        },\n\t\t        onstop:function(_prop,_args){\n\t\t        \t_args = _args || [];\n\t\t            var _effect = _node.effects[_index];\n\t\t            if(!_effect) return;\n\t\t                _effect = _cutr._$recycle(_effect);\n\t\t                _node.effects[_index] = _effect;\n\t\t            if(_node.isLastOne === _index){\n\t\t              _stop.apply(this,_args);\n\t\t            }\n\n\t\t        }._$bind(this,_index)\n\t\t      };\n\t\t    return _options;\n\t\t  };\n\t\t  return _h.__onStart._$aop(function(_event){\n\t\t  \t_event.stopped = !0;\n\t\t    var _list = _event.args;\n\t\t    var _node = _list[0],\n\t\t        _rules= _list[1],\n\t\t        _anim = _list[2],\n\t\t        _stop = _list[3];\n\t\t    _node.isStop = false;\n\t\t    _node.sumTime = 0,_node.isLastOne = 0;\n\t\t    var _effects   = [];\n\t\t    if(_anim.indexOf('all') > -1)\n\t\t      _anim = _doRbAnim(_rules,_anim);\n\t\t    var _animArray = _anim.slice(0,-1);\n\t\t        _animArray = _animArray.split(',');\n\t\t    _node.effects  = [];\n\t\t    _u._$forEach(_animArray,function(_value,_index){\n\t\t        var _options = _doParse(_node,_value,_rules,_stop,_index);\n\t\t        _effects.push({o:_options,c:_doFindCur(_value)});\n\t\t    });\n\t\t    _u._$forEach(_effects,function(_item,_index){\n\t\t      var _effect = _item.c._$allocate(_item.o);\n\t\t      _node.effects[_index] = _effect;\n\t\t      _effect._$play();\n\t\t    });\n\t\t    return this;\n\t\t  });\n\t\t})();\n\n\t\t/**\n\t\t * 取消动画\n\t\t * @param  {Node}   动画节点\n\t\t * @return {nej.h}\n\t\t */\n\t\t_h.__onStop =\n\t\t_h.__onStop._$aop(function(_event){\n\t\t  _event.stopped = !0;\n\t\t  var _list = _event.args;\n\t\t  var _node = _list[0];\n\t\t  _u._$forEach(_node.effects,function(_o){\n\t\t    _node.isStop = true;\n\t\t    if(_o)  _o._$stop(_list[1],_list[3]||false);\n\t\t  });\n\t\t  return this;\n\t\t});\n\n\t\t});\n\n\t// ie8-\n\tNEJ.patch('TR<=4.0',function(){\n\t\t_h.__formatOpacity = function(_value){\n\t\t\treturn 'filter';\n\t\t};\n\n\t\t_h.__formatFrom = function(_node){\n\t\t\tvar _filter = _e._$getStyle(_node,'filter'),\n\t\t    \t_from = parseFloat(_filter.split('=')[1])||0;\n\t\t    return _from;\n\t\t};\n\n\t\t_h.__formatTo = function(_to){\n\t\t\treturn _to * 100;\n\t\t};\n\t});\n\n\treturn _h;\n});"
  },
  {
    "path": "src/util/effect/test/effcet.api.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>effect.api.test</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t    <style type=\"text/css\">\n\t    body{background: #000;}\n\t        .box{font-weight:900;width:100px;height:100px;background:blue;position:absolute;top:500px;left:300px;border:solid red 1px;z-index:0;zoom:1;filter:alpha(opacity=100);}\n\t        .box2{font-weight:900;width:100px;height:100px;background:blue;position:absolute;left:500px;bottom:500px;border:solid red 1px;z-index:0;zoom:1;}\n\t    </style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit dwr test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n    \t<div id=\"box\" class=\"box\"></div>\n    \t<div id=\"box2\" class=\"box2\"></div>\n    \t<button class=\"button\">淡出</button>\n    \t<button class=\"button\">淡入</button>\n    \t<button class=\"button\">移动位置</button>\n    \t<button class=\"button\">toggle</button>\n    \t<button class=\"button\">slide</button>\n        <button class=\"button\">测试属性不变的情况</button>\n        <button class=\"button\">fade stop</button>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./effect.api.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/util/effect/test/effect.api.test.js",
    "content": "var f = function() {\n\t//定义测试模块\n    module(\"effect api test\");\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v'),\n        _p = _('nej.ut');\n    test('effect api test',function(){\n    \texpect(0);\n    \tvar _box = _e._$get('box');\n    \tvar _button = _e._$getByClassName(document.body,'button');\n    \tvar _fdo = function(){\n\t    \t_e._$fadeOut(_box,{\n                delay:1,\n                duration:3,\n                opacity:0.01,\n\t    \t\tonstop:function(_event){\n                    console.log('fadeout stop')\n\t    \t\t\t// _fdi(_box);\n\t    \t\t},\n\t    \t\tonplaystate:function(_event){\n                    console.log('fadeout' + _event.opacity)\n\t    \t\t}\n\t    \t})\n    \t};\n    \tvar _fdi = function(){\n\t    \t_e._$fadeIn(_box,{\n                delay:1,\n                duration:3,\n\t    \t\tonstop:function(_event){\n                    console.log('fadein stop')\n\t    \t\t\t// _fdo(_box);\n\t    \t\t},\n\t    \t\tonplaystate:function(_event){\n                    console.log('fadein' + _event.opacity)\n\t    \t\t}\n\t    \t})\n    \t};\n    \tvar _moveTo = function(){\n    \t\t_e._$moveTo(_box,{top:300,left:500},{\n                duration:[1,1],\n                onstop:function(_event){\n                    console.log('moveTo stop')\n                },\n                onplaystate:function(_event){\n                    console.log('moveTo state')\n                }\n            });\n    \t};\n        var _toggle = function(){\n            _e._$toggleEffect(_box,'height',{value:100,\n                duration:1,\n                onstop:function(_event){\n                },\n                onplaystate:function(_event){\n\n                }\n            });\n        };\n        var _slide = function(){\n            // _e._$slide(_box,'left:+=300',{\n            //     timing:'ease-out',\n            //     delay:0,\n            //     duration:2,\n            //     onstop:function(_event){\n            //         // console.log(_event.left);\n            //     },\n            //     onplaystate:function(_event){\n            //         // console.log(_event.left);\n            //     }\n            // });\n            _e._$slide('box2','left:-=300',{\n                timing:'ease-out',\n                delay:0,\n                duration:5,\n                onstop:function(_event){\n                },\n                onplaystate:function(_event){\n                }\n            })\n        }\n        var _nochange = function(){\n            _e._$slide('box2','bottom:-=300',{\n                timing:'ease-out',\n                delay:0,\n                duration:5,\n                onstop:function(_event){\n                },\n                onplaystate:function(_event){\n                }\n            })\n        };\n        var _fadeStop = function(){\n            _e._$fadeStop('box');\n        }\n    \t_v._$addEvent(_button[0],'click',_fdo);\n    \t_v._$addEvent(_button[1],'click',_fdi);\n    \t_v._$addEvent(_button[2],'click',_moveTo);\n        _v._$addEvent(_button[3],'click',_toggle);\n        _v._$addEvent(_button[4],'click',_slide);\n        _v._$addEvent(_button[5],'click',_nochange);\n        _v._$addEvent(_button[6],'click',_fadeStop);\n    });\n};\nmodule('依赖模块');\ntest('define',function(){expect(0);\n\tdefine('{pro}effect.api.test.js',['{lib}util/effect/effect.api.js'],f);\n});\n"
  },
  {
    "path": "src/util/effect/test/effect.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>effect测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style type=\"text/css\">\n\t\t\t.box{border:none;width:100px;height:100px;background:blue;position:absolute;top:300px;left:300px;border:solid #ccc 1px;z-index:0;opacity:0.3;filter:alpha(opacity=30);font-size:12px;color:red;}\n\t\t\t.box2{border:none;width:600px;height:100px;background:green;position:absolute;top:410px;left:300px;border:solid #ccc 1px;opacity:0.3;z-index:500;opacity:0.6;filter:alpha(opacity=60);}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit effect test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n \t\t<div id=\"box\" class=\"box\">box</div>\n \t\t<div id=\"box2\" class=\"box2\">box2</div>\n \t\t<div>\n\t \t\t<!--button id=\"paused-box\">暂停box动画</button>\n\t \t\t<button id=\"restart-box\">继续box动画</button-->\n\t \t\t<button id=\"stop-box\">终止box动画</button>\n \t\t</div>\n \t\t<div>\n\t \t\t<!--button id=\"paused-box2\">暂停box2动画</button>\n\t \t\t<button id=\"restart-box2\">继续box2动画</button-->\n\t \t\t<button id=\"stop-box2\">终止box2动画</button>\n \t\t</div>\n \t\t<script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./effect.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/util/effect/test/effect.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"effect test\");\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v'),\n        _p = _('nej.ut');\n    \n    //开始单元测试\n    test('effect test', function() {\n        expect(0);\n        var _box = _e._$get('box'),\n            _paused = _e._$get('paused-box'),\n            _restart = _e._$get('restart-box');\n        var _stop = _e._$get('stop-box');\n        var _effect = _p._$$Effect._$allocate(\n            {\n                node:_box,\n                transition:[\n                    {\n                        property:'top',\n                        timing:'ease-in',\n                        delay:1,\n                        duration:10\n                    },\n                    {\n                        property:'z-index',\n                        timing:'ease-in',\n                        delay:2,\n                        duration:10\n                    },\n                    {\n                        property:'font-size',\n                        timing:'ease-out',\n                        delay:3,\n                        duration:10\n                    },\n                    {\n                        property:'font-weight',\n                        timing:'ease-in-out',\n                        delay:4,\n                        duration:10\n                    },\n                    {\n                        property:'opacity',\n                        timing:'ease-in',\n                        delay:5,\n                        duration:10\n                    },\n                    {\n                        property:'left',\n                        timing:'ease-out',\n                        delay:6,\n                        duration:10\n                    },\n                    {\n                        property:'height',\n                        timing:'linear',\n                        delay:7,\n                        duration:10\n                    },\n                    {\n                        property:'margin',\n                        timing:'ease-out',\n                        delay:8,\n                        duration:10\n                    }\n                ],\n                styles:['top:460','z-index:2999','font-size:+=24','font-weight:900','opacity:1','left:800px','height:+=200px','margin:+=10'],\n                onstop:function(){\n\n                },\n                onplaystate:function(){\n\n                }\n            }\n        );\n        // _v._$addEvent(_paused,'click',_effect._$paused._$bind(_effect));\n        // _v._$addEvent(_restart,'click',_effect._$restart._$bind(_effect));\n        _v._$addEvent(_stop,'click',_effect._$stop._$bind(_effect));\n        _effect._$start();\n        // var _effect2 = _p._$$Effect._$allocate({\n        //         node:'box',\n        //         transition:[\n        //             {\n        //                 property:'all',\n        //                 timing:'ease-in',\n        //                 delay:1,\n        //                 duration:10\n        //             }\n        //         ],\n        //         styles:['top:+=460','z-index:999'],\n        //         onstop:function(){\n        //        },\n        //         onplaystate:function(){\n        //         }\n        //     });\n        // _v._$addEvent(_stop,'click',_effect2._$stop._$bind(_effect2));\n        // _effect2._$start();\n        // var _box2 = _e._$get('box2'),\n        //     _paused2 = _e._$get('paused-box2'),\n        //     _restart2 = _e._$get('restart-box2'),\n        //     _stop2 = _e._$get('stop-box2');\n        // var _effect2 = _p._$$Effect._$allocate(\n        //     {\n        //         node:_box2,\n        //         transition:[\n        //             {\n        //                 property:'width',\n        //                 timing:'ease-out',\n        //                 delay:1,\n        //                 duration:3\n        //             },\n        //             {\n        //                 property:'opacity',\n        //                 timing:'ease-out',\n        //                 delay:1,\n        //                 duration:3\n        //             },\n        //             {\n        //                 property:'top',\n        //                 timing:'ease-out',\n        //                 delay:1,\n        //                 duration:4\n        //             }\n        //         ],\n        //         styles:['width:-=200px','opacity:+=0.7','top:100px'],\n        //         onstop:function(){\n\n        //         },\n        //         onplaystate:function(){\n\n        //         }\n        //     }\n        // );\n        // // _v._$addEvent(_paused2,'click',_effect2._$paused._$bind(_effect2));\n        // // _v._$addEvent(_restart2,'click',_effect2._$restart._$bind(_effect2));\n        // _v._$addEvent(_stop2,'click',_effect2._$stop._$bind(_effect2));\n        // _effect2._$start();\n    });\n};\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}effect.test.js',\n    ['{lib}util/effect/effect.js'],f);\n});\n"
  },
  {
    "path": "src/util/encode/base64.js",
    "content": "/*\n * ------------------------------------------\n * Base64编解码接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/encode/base64 */\nNEJ.define([\n    'base/global',\n    'base/util'\n],function(NEJ,_u,_p,_o,_f,_r){\n    // implement\n    var __b64tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',\n        __b64char = {},\n        __b64index = {};\n    // creates two arrays which makes base64 en- and decoding faster\n    // this speed is noticeable especially when coding larger texts (>5k or so)\n    for(var i=0,l=__b64tab.length,c;i<l;i++){\n        c = __b64tab.charAt(i);\n        __b64char[i] = c;\n        __b64index[c] = i;\n    }\n    // returns an array of byterepresenting dezimal numbers which represent the\n    // plaintext in an UTF-8 encoded version. Expects a string.\n    // This function includes an exception management for those nasty browsers like\n    // NN401, which returns negative decimal numbers for chars>128. I hate it!!\n    // This handling is unfortunately limited to the user's charset. Anyway, it works\n    // in most of the cases! Special signs with an unicode>256 return numbers, which\n    // can not be converted to the actual unicode and so not to the valid utf-8\n    // representation. Anyway, this function does always return values which can not\n    // misinterpretd by RC4 or base64 en- or decoding, because every value is >0 and\n    // <255!!\n    // Arrays are faster and easier to handle in b64 encoding or encrypting....\n    var __bin2utf8 = function(_binarray){\n        var _index = 0,c,\n            _result = [];\n        while(_index<_binarray.length){\n            c = _binarray[_index];\n            // all the signs of asci => 1byte\n            if (c<128){\n                _result.push(String.fromCharCode(c));\n                _index++;\n            // all the signs between 127 and 2047 => 2byte\n            }else if(c>191&&c<224){\n                _result.push(String.fromCharCode(((c&31)<<6)|(_binarray[_index+1]&63)));\n                _index += 2;\n            // all the signs between 2048 and 66536 => 3byte\n            }else{\n                _result.push(String.fromCharCode(((c&15)<<12)|((_binarray[_index+1]&63)<<6)|(_binarray[_index+2]&63)));\n                _index += 3;\n            }\n        }\n        return _result.join('');\n    };\n    // returns plaintext from an array of bytesrepresenting dezimal numbers, which\n    // represent an UTF-8 encoded text; browser which does not understand unicode\n    // like NN401 will show \"?\"-signs instead\n    // expects an array of byterepresenting decimals; returns a string\n    var __utf82bin = (function(){\n        var _line = /\\r\\n/g;\n        return function(_data){\n            _data = _data.replace(_line,'\\n');\n            var _result = [],\n                _test = String.fromCharCode(237);\n            if (_test.charCodeAt(0)<0)\n                for(var i=0,l=_data.length,c;i<l;i++){\n                    c = _data.charCodeAt(i);\n                    c>0 ? _result.push(c)\n                        : _result.push(((256+c)>>6)|192,((256+c)&63)|128);\n                }\n            else\n                for(var i=0,l=_data.length,c;i<l;i++){\n                    c = _data.charCodeAt(i);\n                    // all the signs of asci => 1byte\n                    if (c<128)\n                        _result.push(c);\n                    // all the signs between 127 and 2047 => 2byte\n                    else if((c>127)&&(c<2048))\n                        _result.push((c>>6)|192,(c&63)|128);\n                    // all the signs between 2048 and 66536 => 3byte\n                    else\n                        _result.push((c>>12)|224,((c>>6)&63)|128,(c&63)|128);\n                }\n            return _result;\n        };\n    })();\n    // creates a base64 encoded text out of an array of byerepresenting dezimals\n    // it is really base64 :) this makes serversided handling easier\n    // expects an array; returns a string\n    var __bin2b64 = function(_binarray){\n        var _index = 0,\n            _result = [],\n            _mode = _binarray.length%3;\n        // this is for the padding\n        if (_mode==1)\n            _binarray.push(0,0);\n        if (_mode==2)\n            _binarray.push(0);\n        // from here conversion\n        while(_index<_binarray.length){\n            _result.push(__b64char[_binarray[_index]>>2],\n                         __b64char[((_binarray[_index]&3)<<4)|(_binarray[_index+1]>>4)],\n                         __b64char[((_binarray[_index+1]&15)<<2)|(_binarray[_index+2]>>6)],\n                         __b64char[_binarray[_index+2]&63]);\n            _index += 3;\n        }\n        // this is again for the padding\n        if (_mode == 1)\n            _result[_result.length-1] =\n            _result[_result.length-2] = '=';\n        if (_mode == 2)\n            _result[_result.length-1] = '=';\n        // we join the array to return a textstring\n        return _result.join('');\n    };\n    // returns array of byterepresenting numbers created of an base64 encoded text\n    // it is still the slowest function in this modul; I hope I can make it faster\n    // expects string; returns an array\n    var __b642bin = (function(){\n        var _clear = /\\n|\\r|=/g;\n        return function(_data){\n            var _index = 0,\n                _result = [];\n            // here we fix this CRLF sequenz created by MS-OS;\n            _data = _data.replace(_clear,'');\n            for(var i=0,l=_data.length;i<l;i+=4)\n                _result.push((__b64index[_data.charAt(i)]<<2)|(__b64index[_data.charAt(i+1)]>>4),\n                            ((__b64index[_data.charAt(i+1)]&15)<<4)|(__b64index[_data.charAt(i+2)]>>2),\n                            ((__b64index[_data.charAt(i+2)]&3)<<6)|(__b64index[_data.charAt(i+3)]));\n            // check list\n            var _length = _result.length,\n                _mode = _data.length%4;\n            if (_mode==2)\n                _result = _result.slice(0,_length-2);\n            if (_mode==3)\n                _result = _result.slice(0,_length-1);\n            return _result;\n        };\n    })();\n    /**\n     * Base64解码数据\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/encode/base64'\n     * ],function(_u){\n     *     // 测试一些字符，编码，反编码\n     *     var _arr = [\n     *         'a','null','function','error',\n     *         'return','switch','if','!0',\n     *         'UNdefined','NULL','Function',\n     *         'ERROR','return 1'\n     *     ];\n     *     for(var i=0,l=_arr.length,_it,_b64,_str;i<l;i++){\n     *         _it = _arr[i];\n     *         _b64 = _u._$str2b64(_it);\n     *         _str = _u._$b642str(_b64);\n     *     }\n     * });\n     * ```\n     * \n     * @method module:util/encode/base64._$b642str\n     * @see    module:util/encode/base64._$str2b64\n     * @param  {String} arg0 - 数据\n     * @return {String}        解码后数据\n     */\n    _p._$b642str = function(_data){\n        return __bin2utf8(__b642bin(_data));\n    };\n    /**\n     * Base64编码数据\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/encode/base64'\n     * ],function(_u){\n     *     // 测试一些字符，编码，反编码\n     *     var _arr = [\n     *         'a','null','function','error',\n     *         'return','switch','if','!0',\n     *         'UNdefined','NULL','Function',\n     *         'ERROR','return 1'\n     *     ];\n     *     for(var i=0,l=_arr.length,_it,_b64,_str;i<l;i++){\n     *         _it = _arr[i];\n     *         _b64 = _u._$str2b64(_it);\n     *         _str = _u._$b642str(_b64);\n     *     }\n     * });\n     * ```\n     * \n     * @method module:util/encode/base64._$str2b64\n     * @see    module:util/encode/base64._$b642str\n     * @param  {String} arg0 - 数据\n     * @return {String}        编码后数据\n     */\n    _p._$str2b64 = function(_data){\n        try{\n            // only for x0000-x00ff\n            return window.btoa(_data);\n        }catch(ex){\n            return __bin2b64(__utf82bin(_data));\n        }\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.u'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/encode/crc32.js",
    "content": "/*\n *  Javascript CRC32\n *  http://www.webtoolkit.info/\n **/\n/** @module util/encode/crc32 */\nNEJ.define([\n    'base/global'\n],function(NEJ,_p,_o,_f,_r){\n    /**\n     * 生成32位循环冗余校验码多项式，用于检查传输的数据的完整性\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/encode/crc32'\n     * ],function(_u){\n     *     var _result = _u._$crc32('Thequickbrownfoxjumpedoverthelazydog.');\n     * });\n     * ```\n     * \n     * @method module:util/encode/crc32._$crc32\n     * @param  {String} arg0 - 待校验数据\n     * @return {Number}        校验码\n     */\n    _p._$crc32 = function(H){function k(string){string=string.replace(/\\r\\n/g,\"\\n\");var F=\"\";for(var n=0;n<string.length;n++){var c=string.charCodeAt(n);if(c<128){F+=String.fromCharCode(c);}else if((c>127)&&(c<2048)){F+=String.fromCharCode((c>>6)|192);F+=String.fromCharCode((c&63)|128);}else{F+=String.fromCharCode((c>>12)|224);F+=String.fromCharCode(((c>>6)&63)|128);F+=String.fromCharCode((c&63)|128);}}return F;};H=k(H);var table=\"00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F 63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E 7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D\";var crc=0;var x=0;var y=0;crc=crc^(-1);for(var i=0,t=H.length;i<t;i++){y=(crc^H.charCodeAt(i))&0xFF;x=\"0x\"+table.substr(y*9,8);crc=(crc>>>8)^x;}return crc^(-1);};\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.u'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/encode/demo/json.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - JSON接口</title>\n    <meta charset=\"utf-8\" />\n  </head>\n  <body>\n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            'util/encode/json'\n        ],function(){\n            console.log(JSON.parse('{\"a\":20}'));\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/encode/demo/md5.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - JSON接口</title>\n    <meta charset=\"utf-8\" />\n  </head>\n  <body>\n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            'util/encode/md5'\n        ],function(u){\n            var x = u._$str2hex('{\"a\":\"中文\"}',false);\n            console.log(x);\n\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/encode/json.js",
    "content": "NEJ.define(['{platform}json.js'],function(){return JSON;});"
  },
  {
    "path": "src/util/encode/md5.js",
    "content": "/*\n * ------------------------------------------\n * SHA/MD5编解码接口实现文件\n * 参考：http://pajhome.org.uk/crypt/md5/\n *  MD5：http://www.ietf.org/rfc/rfc1321.txt\n * HMAC：http://www.ietf.org/rfc/rfc2104.txt\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/encode/md5 */\nNEJ.define([\n    'base/global'\n],function(NEJ,_p,_o,_f,_r){\n    // bits per input character. 8 - ASCII; 16 - Unicode\n    var __chrsz = 8;\n    /*\n     * Bitwise rotate a 32-bit number to the left.\n     */\n    var __rol = function(_number,_count){\n        return (_number<<_count)|(_number>>>(32-_count));\n    };\n    /*\n     * Add integers, wrapping at 2^32. This uses 16-bit operations internally\n     * to work around bugs in some JS interpreters.\n     */\n    var __add = function(x,y){\n        var _lsw = (x&0xFFFF)+(y&0xFFFF),\n            _msw = (x>>16)+(y>>16)+(_lsw>>16);\n        return (_msw<<16)|(_lsw&0xFFFF);\n    };\n    /*\n     * Perform the appropriate triplet combination function for the current\n     * iteration\n     */\n    var __sha1ft = function(t,b,c,d){\n        if (t<20) return (b&c)|((~b)&d);\n        if (t<40) return  b^c^d;\n        if (t<60) return (b&c)|(b&d)|(c&d);\n        return b^c^d;\n    };\n    /*\n     * Determine the appropriate additive constant for the current iteration\n     */\n    var __sha1kt = function(t){\n        if (t<20) return 1518500249;\n        if (t<40) return 1859775393;\n        if (t<60) return -1894007588;\n        return -899497514;\n    };\n    /*\n     * Convert an 8-bit or 16-bit string to an array of big-endian or little-endian words\n     */\n    var __str2bin = (function(){\n        var _lmove = function(i){return i%32;},\n            _bmove = function(i){return 32-__chrsz-i%32;};\n        return function(_str,_little){\n            var _bin  = [],\n                _mask = (1<<__chrsz)-1,\n                _move = _little?_lmove:_bmove;\n            for (var i=0,l=_str.length*__chrsz;i<l;i+=__chrsz)\n                _bin[i>>5] |= (_str.charCodeAt(i/__chrsz)&_mask)<<_move(i);\n            return _bin;\n        };\n    })();\n    /*\n     * Convert an array of big-endian or little-endian words to a hex string.\n     */\n    var __bin2hex = (function(){\n        // hex output table.\n        var _hextab = '0123456789abcdef',\n            _lmove  = function(i){return i%4;},\n            _bmove  = function(i){return 3-i%4;};\n        return function(_binarray,_little){\n            var _arr = [],\n                _move = _little?_lmove:_bmove;\n            for(var i=0,l=_binarray.length*4;i<l;i++){\n                _arr.push(_hextab.charAt((_binarray[i>>2]>>(_move(i)*8+4))&0xF)\n                         +_hextab.charAt((_binarray[i>>2]>>(_move(i)*8))&0xF));\n            }\n            return _arr.join('');\n        };\n    })();\n    /*\n     * Convert an array of big-endian or little-endian words to a string\n     */\n    var __bin2str = (function(){\n        var _lmove = function(i){return i%32;},\n            _bmove = function(i){return 32-__chrsz-i%32;};\n        return function(_bin,_little){\n            var _arr  = [],\n                _mask = (1<<__chrsz)-1,\n                _move = _little?_lmove:_bmove;\n            for(var i=0,l=_bin.length*32;i<l;i+=__chrsz)\n                _arr.push(String.fromCharCode((_bin[i>>5]>>>_move(i))&_mask));\n            return _arr.join('');\n        };\n    })();\n    /*\n     * Convert an array of big-endian or little-endian words to a base-64 string\n     */\n    var __bin2b64 = (function(){\n        var _b64pad = '=', // base-64 pad character. \"=\" for strict RFC compliance\n            _b64tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',\n            _lmove  = function(i){return i%4;},\n            _bmove  = function(i){return 3-i%4;};\n        return function(_binarray,_little){\n            var _arr = [],\n                _move = _little?_lmove:_bmove;\n            for(var i=0,_triplet;i<_binarray.length*4;i+=3){\n                _triplet = (((_binarray[i>>2]>>8*_move(i))&0xFF)<<16)\n                         | (((_binarray[i+1>>2]>>8*_move(i+1))&0xFF)<<8)\n                         | ((_binarray[i+2>>2]>>8*_move(i+2))&0xFF);\n                for(var j=0;j<4;j++)\n                    _arr.push((i*8+j*6>_binarray.length*32) ? _b64pad\n                             : _b64tab.charAt((_triplet>>6*(3-j))&0x3F));\n            }\n            return _arr.join('');\n        };\n    })();\n    /*\n     * These functions implement the four basic operations the algorithm uses.\n     */\n    var __md5cm = function(q,a,b,x,s,t){\n        return __add(__rol(__add(__add(a,q),__add(x,t)),s),b);\n    };\n    var __md5ff = function(a,b,c,d,x,s,t){\n        return __md5cm((b&c)|((~b)&d),a,b,x,s,t);\n    };\n    var __md5gg = function(a,b,c,d,x,s,t){\n        return __md5cm((b&d)|(c&(~d)),a,b,x,s,t);\n    };\n    var __md5hh = function(a,b,c,d,x,s,t){\n        return __md5cm(b^c^d,a,b,x,s,t);\n    };\n    var __md5ii = function(a,b,c,d,x,s,t){\n        return __md5cm(c^(b|(~d)),a,b,x,s,t);\n    };\n    /*\n     * Calculate the MD5 of an array of little-endian words, and a bit length\n     */\n    var __data2md5  = function(x,y){\n        x[y>>5] |= 0x80<<((y)%32);\n        x[(((y+64)>>>9)<<4)+14] = y;\n        var a = 1732584193,\n            b = -271733879,\n            c = -1732584194,\n            d = 271733878;\n        for(var i=0,l=x.length,_oa,_ob,_oc,_od;i<l;i+=16){\n            _oa = a; _ob = b; _oc = c; _od = d;\n            a = __md5ff(a, b, c, d, x[i+ 0], 7 , -680876936);\n            d = __md5ff(d, a, b, c, x[i+ 1], 12, -389564586);\n            c = __md5ff(c, d, a, b, x[i+ 2], 17,  606105819);\n            b = __md5ff(b, c, d, a, x[i+ 3], 22, -1044525330);\n            a = __md5ff(a, b, c, d, x[i+ 4], 7 , -176418897);\n            d = __md5ff(d, a, b, c, x[i+ 5], 12,  1200080426);\n            c = __md5ff(c, d, a, b, x[i+ 6], 17, -1473231341);\n            b = __md5ff(b, c, d, a, x[i+ 7], 22, -45705983);\n            a = __md5ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);\n            d = __md5ff(d, a, b, c, x[i+ 9], 12, -1958414417);\n            c = __md5ff(c, d, a, b, x[i+10], 17, -42063);\n            b = __md5ff(b, c, d, a, x[i+11], 22, -1990404162);\n            a = __md5ff(a, b, c, d, x[i+12], 7 ,  1804603682);\n            d = __md5ff(d, a, b, c, x[i+13], 12, -40341101);\n            c = __md5ff(c, d, a, b, x[i+14], 17, -1502002290);\n            b = __md5ff(b, c, d, a, x[i+15], 22,  1236535329);\n            a = __md5gg(a, b, c, d, x[i+ 1], 5 , -165796510);\n            d = __md5gg(d, a, b, c, x[i+ 6], 9 , -1069501632);\n            c = __md5gg(c, d, a, b, x[i+11], 14,  643717713);\n            b = __md5gg(b, c, d, a, x[i+ 0], 20, -373897302);\n            a = __md5gg(a, b, c, d, x[i+ 5], 5 , -701558691);\n            d = __md5gg(d, a, b, c, x[i+10], 9 ,  38016083);\n            c = __md5gg(c, d, a, b, x[i+15], 14, -660478335);\n            b = __md5gg(b, c, d, a, x[i+ 4], 20, -405537848);\n            a = __md5gg(a, b, c, d, x[i+ 9], 5 ,  568446438);\n            d = __md5gg(d, a, b, c, x[i+14], 9 , -1019803690);\n            c = __md5gg(c, d, a, b, x[i+ 3], 14, -187363961);\n            b = __md5gg(b, c, d, a, x[i+ 8], 20,  1163531501);\n            a = __md5gg(a, b, c, d, x[i+13], 5 , -1444681467);\n            d = __md5gg(d, a, b, c, x[i+ 2], 9 , -51403784);\n            c = __md5gg(c, d, a, b, x[i+ 7], 14,  1735328473);\n            b = __md5gg(b, c, d, a, x[i+12], 20, -1926607734);\n            a = __md5hh(a, b, c, d, x[i+ 5], 4 , -378558);\n            d = __md5hh(d, a, b, c, x[i+ 8], 11, -2022574463);\n            c = __md5hh(c, d, a, b, x[i+11], 16,  1839030562);\n            b = __md5hh(b, c, d, a, x[i+14], 23, -35309556);\n            a = __md5hh(a, b, c, d, x[i+ 1], 4 , -1530992060);\n            d = __md5hh(d, a, b, c, x[i+ 4], 11,  1272893353);\n            c = __md5hh(c, d, a, b, x[i+ 7], 16, -155497632);\n            b = __md5hh(b, c, d, a, x[i+10], 23, -1094730640);\n            a = __md5hh(a, b, c, d, x[i+13], 4 ,  681279174);\n            d = __md5hh(d, a, b, c, x[i+ 0], 11, -358537222);\n            c = __md5hh(c, d, a, b, x[i+ 3], 16, -722521979);\n            b = __md5hh(b, c, d, a, x[i+ 6], 23,  76029189);\n            a = __md5hh(a, b, c, d, x[i+ 9], 4 , -640364487);\n            d = __md5hh(d, a, b, c, x[i+12], 11, -421815835);\n            c = __md5hh(c, d, a, b, x[i+15], 16,  530742520);\n            b = __md5hh(b, c, d, a, x[i+ 2], 23, -995338651);\n            a = __md5ii(a, b, c, d, x[i+ 0], 6 , -198630844);\n            d = __md5ii(d, a, b, c, x[i+ 7], 10,  1126891415);\n            c = __md5ii(c, d, a, b, x[i+14], 15, -1416354905);\n            b = __md5ii(b, c, d, a, x[i+ 5], 21, -57434055);\n            a = __md5ii(a, b, c, d, x[i+12], 6 ,  1700485571);\n            d = __md5ii(d, a, b, c, x[i+ 3], 10, -1894986606);\n            c = __md5ii(c, d, a, b, x[i+10], 15, -1051523);\n            b = __md5ii(b, c, d, a, x[i+ 1], 21, -2054922799);\n            a = __md5ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);\n            d = __md5ii(d, a, b, c, x[i+15], 10, -30611744);\n            c = __md5ii(c, d, a, b, x[i+ 6], 15, -1560198380);\n            b = __md5ii(b, c, d, a, x[i+13], 21,  1309151649);\n            a = __md5ii(a, b, c, d, x[i+ 4], 6 , -145523070);\n            d = __md5ii(d, a, b, c, x[i+11], 10, -1120210379);\n            c = __md5ii(c, d, a, b, x[i+ 2], 15,  718787259);\n            b = __md5ii(b, c, d, a, x[i+ 9], 21, -343485551);\n            a = __add(a, _oa);\n            b = __add(b, _ob);\n            c = __add(c, _oc);\n            d = __add(d, _od);\n        }   return [a, b, c, d];\n    };\n    /*\n     * Calculate the HMAC-MD5, of a key and some data\n     */\n    var __data2hmacmd5 = function(_key,_data){\n        var _bkey = __str2bin(_key,!0);\n        if (_bkey.length>16)\n            _bkey = __data2md5(_bkey,_key.length*__chrsz);\n\n        var _ipad = Array(16),\n            _opad = Array(16);\n        for(var i=0;i<16;i++){\n            _ipad[i] = _bkey[i]^0x36363636;\n            _opad[i] = _bkey[i]^0x5C5C5C5C;\n        }\n\n        var _hash = __data2md5(_ipad.concat(\n                               __str2bin(_data,!0)),\n                               512+_data.length*__chrsz);\n        return __data2md5(_opad.concat(_hash),512+128);\n    };\n    /*\n     * Calculate the SHA-1 of an array of big-endian words, and a bit length\n     */\n    var __data2sha1 = function(x,_length){\n        /* append padding */\n        x[_length>>5] |= 0x80<<(24-_length%32);\n        x[((_length+64>>9)<<4)+15] = _length;\n        var w = Array(80),  a = 1732584193,\n            b = -271733879, c = -1732584194,\n            d = 271733878,  e = -1009589776;\n        for(var i=0,l=x.length,_olda,\n            _oldb,_oldc,_oldd,_olde;i<l;i+=16){\n            _olda = a; _oldb = b;\n            _oldc = c; _oldd = d; _olde = e;\n            for(var j=0;j<80;j++){\n                w[j] = j<16 ? x[i+j]\n                            : __rol(w[j-3]^w[j-8]^w[j-14]^w[j-16],1);\n                var t = __add(__add(__rol(a,5),\n                              __sha1ft(j,b,c,d)),\n                              __add(__add(e,w[j]),\n                              __sha1kt(j)));\n                e = d; d = c;\n                c = __rol(b,30);\n                b = a; a = t;\n            }\n            a = __add(a,_olda);\n            b = __add(b,_oldb);\n            c = __add(c,_oldc);\n            d = __add(d,_oldd);\n            e = __add(e,_olde);\n        }\n        return [a,b,c,d,e];\n    };\n    /*\n     * Calculate the HMAC-SHA1 of a key and some data\n     */\n    var __data2hmacsha1 = function(_key,_data){\n        var _bkey = __str2bin(_key);\n        if (_bkey.length>16)\n            _bkey = __data2sha1(_bkey,_key.length*__chrsz);\n\n        var _ipad = Array(16),\n            _opad = Array(16);\n        for(var i=0;i<16;i++){\n            _ipad[i] = _bkey[i]^0x36363636;\n            _opad[i] = _bkey[i]^0x5C5C5C5C;\n        }\n        var _hash = __data2sha1(_ipad.concat(__str2bin(\n                                _data)),512+_data.length*__chrsz);\n        return __data2sha1(_opad.concat(_hash),512+160);\n    };\n    /**\n     * HMAC-SHA1编码数据输出十六进制串\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/encode/md5'\n     * ],function(_u){\n     *     // 密钥123，加密abc，输出十六进制编码串\n     *     // a3c024f01cccb3b63457d848b0d2f89c1f744a3d\n     *     var _result = _u._$hmacsha12hex('123','abc');\n     * });\n     * ```\n     * \n     * @method module:util/encode/md5._$hmacsha12hex\n     * @param  {String}   arg0 - 密钥\n     * @param  {Variable} arg1 - 数据\n     * @return {String}          十六进制编码串\n     */\n    _p._$hmacsha12hex = function(_key,_data) {\n        return __bin2hex(__data2hmacsha1(_key,_data));\n    };\n    /**\n     * HMAC-SHA1编码数据输出Base64串\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/encode/md5'\n     * ],function(_u){\n     *     // 密钥123，加密abc，输出Base64编码串\n     *     // o8Ak8BzMs7Y0V9hIsNL4nB90Sj0=\n     *     var _result = _u._$hmacsha12b64('123','abc');\n     * });\n     * ```\n     * \n     * @method module:util/encode/md5._$hmacsha12b64\n     * @param  {String}   arg0 - 密钥\n     * @param  {Variable} arg1 - 数据\n     * @return {String}          Base64编码串\n     */\n    _p._$hmacsha12b64 = function(_key,_data) {\n        return __bin2b64(__data2hmacsha1(_key,_data));\n    };\n    /**\n     * HMAC-SHA1编码数据输出字符串\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/encode/md5'\n     * ],function(_u){\n     *     // 密钥123，加密abc，输出字符串\n     *     // £À$ð\u001cÌ³¶4WØH°Òø\u001ftJ=\n     *     var _result = _u._$hmacsha12str('123','abc');\n     * });\n     * ```\n     * \n     * @method module:util/encode/md5._$hmacsha12str\n     * @param  {String}   arg0 - 密钥\n     * @param  {Variable} arg1 - 数据\n     * @return {String}          编码串\n     */\n    _p._$hmacsha12str = function(_key,_data) {\n        return __bin2str(__data2hmacsha1(_key,_data));\n    };\n    /**\n     * HMAC-MD5编码数据输出十六进制串\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/encode/md5'\n     * ],function(_u){\n     *     // 密钥123，加密abc，输出十六进制串\n     *     // b2a1ec0f3e0607099d7f39791c04e9a4\n     *     var _result = _u._$hmacsha12str('123','abc');\n     * });\n     * ```\n     * \n     * @method module:util/encode/md5._$hmacsha12str\n     * @param  {String} arg0 - 密钥\n     * @param  {String} arg1 - 数据\n     * @return {String}        十六进制串\n     */\n    _p._$hmacmd52hex = function(_key,_data){\n        return __bin2hex(__data2hmacmd5(_key,_data),!0);\n    };\n    /**\n     * HMAC-MD5编码数据输出Base64串\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/encode/md5'\n     * ],function(_u){\n     *     // 密钥123，加密abc，输出Base64串\n     *     // sqHsDz4GBwmdfzl5HATppA==\n     *     var _result = _u._$hmacmd52b64('123','abc');\n     * });\n     * ```\n     * \n     * @method module:util/encode/md5._$hmacmd52b64\n     * @param  {String} arg0 - 密钥\n     * @param  {String} arg1 - 数据\n     * @return {String}        Base64串\n     */\n    _p._$hmacmd52b64 = function(_key,_data){\n        return __bin2b64(__data2hmacmd5(_key,_data),!0);\n    };\n    /**\n     * HMAC-MD5编码数据输出字符串\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/encode/md5'\n     * ],function(_u){\n     *     // 密钥123，加密abc，输出字符串\n     *     // ²¡ì\u000f>\u0006\u0007 9y\u001c\u0004é¤\n     *     var _result = _u._$hmacmd52str('123','abc');\n     * });\n     * ```\n     * \n     * @method module:util/encode/md5._$hmacmd52str\n     * @param  {String} arg0 - 密钥\n     * @param  {String} arg1 - 数据\n     * @return {String}        字符串\n     */\n    _p._$hmacmd52str = function(_key,_data){\n        return __bin2str(__data2hmacmd5(_key,_data),!0);\n    };\n    /**\n     * SHA1编码数据输出十六进制串\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/encode/md5'\n     * ],function(_u){\n     *     // 输入数据123，输出十六进制编码串\n     *     // 40bd001563085fc35165329ea1ff5c5ecbdbbeef\n     *     var _result = _u._$sha12hex('123');\n     * });\n     * ```\n     * \n     * @method module:util/encode/md5._$sha12hex\n     * @param  {Variable} arg0 - 数据\n     * @return {String}          十六进制编码串\n     */\n    _p._$sha12hex = function(_data) {\n        return __bin2hex(__data2sha1(\n                         __str2bin(_data),\n                         _data.length*__chrsz));\n    };\n    /**\n     * SHA1编码数据输出Base64串\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/encode/md5'\n     * ],function(_u){\n     *     // 输入数据123，输出Base64编码串\n     *     // QL0AFWMIX8NRZTKeof9cXsvbvu8=\n     *     var _result = _u._$sha12b64('123');\n     * });\n     * ```\n     * \n     * @method module:util/encode/md5._$sha12b64\n     * @param  {Variable} arg0 - 数据\n     * @return {String}          Base64编码串\n     */\n    _p._$sha12b64 = function(_data) {\n        return __bin2b64(__data2sha1(\n                         __str2bin(_data),\n                         _data.length*__chrsz));\n    };\n    /**\n     * SHA1编码数据输出字符串\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/encode/md5'\n     * ],function(_u){\n     *     // 输入数据123，输出字符串\n     *     // @½\u0015c\b_ÃQe2¡ÿ\\^ËÛ¾ï\n     *     var _result = _u._$sha12str('123');\n     * });\n     * ```\n     * \n     * @method module:util/encode/md5._$sha12str\n     * @param  {Variable} arg0 - 数据\n     * @return {String}          字符串\n     */\n    _p._$sha12str = function(_data) {\n        return __bin2str(__data2sha1(\n                         __str2bin(_data),\n                         _data.length*__chrsz));\n    };\n    /**\n     * MD5编码数据输出十六进制串\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/encode/md5'\n     * ],function(_u){\n     *     // 输入数据123，输出十六进制串\n     *     // 202cb962ac59075b964b07152d234b70\n     *     var _result = _u._$md52hex('123');\n     * });\n     * ```\n     * \n     * @method module:util/encode/md5._$md52hex\n     * @param  {String} arg0 - 数据\n     * @return {String}        十六进制串\n     */\n    _p._$md52hex = function(_data){\n        return __bin2hex(__data2md5(\n                         __str2bin(_data,!0),\n                         _data.length*__chrsz),!0);\n    };\n    /**\n     * MD5编码数据输出Base64串\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/encode/md5'\n     * ],function(_u){\n     *     // 输入数据123，输出Base64串\n     *     // ICy5YqxZB1uWSwcVLSNLcA==\n     *     var _result = _u._$md52b64('123');\n     * });\n     * ```\n     * \n     * @method module:util/encode/md5._$md52b64\n     * @param  {String} arg0 - 数据\n     * @return {String}        Base64串\n     */\n    _p._$md52b64 = function(_data){\n        return __bin2b64(__data2md5(\n                         __str2bin(_data,!0),\n                         _data.length*__chrsz),!0);\n    };\n    /**\n     * MD5编码数据输出字符串\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/encode/md5'\n     * ],function(_u){\n     *     // 输入数据123，输出字符串\n     *     //  ,¹b¬Y\u0007[K\u0007\u0015-#Kp\n     *     var _result = _u._$md52str('123');\n     * });\n     * ```\n     * \n     * @method module:util/encode/md5._$md52str\n     * @param  {String} arg0 - 数据\n     * @return {String}        字符串\n     */\n    _p._$md52str = function(_data){\n        return __bin2str(__data2md5(\n                         __str2bin(_data,!0),\n                         _data.length*__chrsz),!0);\n    };\n    /**\n     * 字符串转十六进制,低位补零\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/encode/md5'\n     * ],function(_u){\n     *     // 输入数据0，输出十六进制串\n     *     // 30000000\n     *     var _result = _u._$str2hex('0');\n     * });\n     * ```\n     * \n     * @method module:util/encode/md5._$str2hex\n     * @param  {String}  arg0 - 字符串\n     * @param  {Boolean} arg1 - 是否大端序\n     * @return {String}         十六进制串\n     */\n    _p._$str2hex = function(_data,_big){\n        return __bin2hex(__str2bin(_data,!_big),!_big);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.u'),_p);\n    }\n    \n    return _p;\n});"
  },
  {
    "path": "src/util/encode/platform/3rd.json.js",
    "content": "/*! JSON v3.2.5 | http://bestiejs.github.io/json3 | Copyright 2012-2013, Kit Cambridge | http://kit.mit-license.org */\n;(function(){var o=!0,w=null;\n(function(B){function v(a){if(\"bug-string-char-index\"==a)return\"a\"!=\"a\"[0];var f,c=\"json\"==a;if(c||\"json-stringify\"==a||\"json-parse\"==a){if(\"json-stringify\"==a||c){var d=k.stringify,b=\"function\"==typeof d&&l;if(b){(f=function(){return 1}).toJSON=f;try{b=\"0\"===d(0)&&\"0\"===d(new Number)&&'\"\"'==d(new String)&&d(m)===r&&d(r)===r&&d()===r&&\"1\"===d(f)&&\"[1]\"==d([f])&&\"[null]\"==d([r])&&\"null\"==d(w)&&\"[null,null,null]\"==d([r,m,w])&&'{\"a\":[1,true,false,null,\"\\\\u0000\\\\b\\\\n\\\\f\\\\r\\\\t\"]}'==d({a:[f,o,!1,w,\"\\x00\\u0008\\n\\u000c\\r\\t\"]})&&\n\"1\"===d(w,f)&&\"[\\n 1,\\n 2\\n]\"==d([1,2],w,1)&&'\"-271821-04-20T00:00:00.000Z\"'==d(new Date(-864E13))&&'\"+275760-09-13T00:00:00.000Z\"'==d(new Date(864E13))&&'\"-000001-01-01T00:00:00.000Z\"'==d(new Date(-621987552E5))&&'\"1969-12-31T23:59:59.999Z\"'==d(new Date(-1))}catch(n){b=!1}}if(!c)return b}if(\"json-parse\"==a||c){a=k.parse;if(\"function\"==typeof a)try{if(0===a(\"0\")&&!a(!1)){f=a('{\"a\":[1,true,false,null,\"\\\\u0000\\\\b\\\\n\\\\f\\\\r\\\\t\"]}');var e=5==f.a.length&&1===f.a[0];if(e){try{e=!a('\"\\t\"')}catch(g){}if(e)try{e=\n1!==a(\"01\")}catch(i){}}}}catch(O){e=!1}if(!c)return e}return b&&e}}var m={}.toString,p,C,r,D=typeof define===\"function\"&&define.amd,k=\"object\"==typeof exports&&exports;k||D?\"object\"==typeof JSON&&JSON?k?(k.stringify=JSON.stringify,k.parse=JSON.parse):k=JSON:D&&(k=B.JSON={}):k=B.JSON||(B.JSON={});var l=new Date(-3509827334573292);try{l=-109252==l.getUTCFullYear()&&0===l.getUTCMonth()&&1===l.getUTCDate()&&10==l.getUTCHours()&&37==l.getUTCMinutes()&&6==l.getUTCSeconds()&&708==l.getUTCMilliseconds()}catch(P){}if(!v(\"json\")){var s=\nv(\"bug-string-char-index\");if(!l)var t=Math.floor,J=[0,31,59,90,120,151,181,212,243,273,304,334],z=function(a,f){return J[f]+365*(a-1970)+t((a-1969+(f=+(f>1)))/4)-t((a-1901+f)/100)+t((a-1601+f)/400)};if(!(p={}.hasOwnProperty))p=function(a){var f={},c;if((f.__proto__=w,f.__proto__={toString:1},f).toString!=m)p=function(a){var f=this.__proto__,a=a in(this.__proto__=w,this);this.__proto__=f;return a};else{c=f.constructor;p=function(a){var f=(this.constructor||c).prototype;return a in this&&!(a in f&&\nthis[a]===f[a])}}f=w;return p.call(this,a)};var K={\"boolean\":1,number:1,string:1,undefined:1};C=function(a,f){var c=0,b,h,n;(b=function(){this.valueOf=0}).prototype.valueOf=0;h=new b;for(n in h)p.call(h,n)&&c++;b=h=w;if(c)c=c==2?function(a,f){var c={},b=m.call(a)==\"[object Function]\",d;for(d in a)!(b&&d==\"prototype\")&&!p.call(c,d)&&(c[d]=1)&&p.call(a,d)&&f(d)}:function(a,f){var c=m.call(a)==\"[object Function]\",b,d;for(b in a)!(c&&b==\"prototype\")&&p.call(a,b)&&!(d=b===\"constructor\")&&f(b);(d||p.call(a,\nb=\"constructor\"))&&f(b)};else{h=[\"valueOf\",\"toString\",\"toLocaleString\",\"propertyIsEnumerable\",\"isPrototypeOf\",\"hasOwnProperty\",\"constructor\"];c=function(a,f){var c=m.call(a)==\"[object Function]\",b,d;if(d=!c)if(d=typeof a.constructor!=\"function\"){d=typeof a.hasOwnProperty;d=d==\"object\"?!!a.hasOwnProperty:!K[d]}d=d?a.hasOwnProperty:p;for(b in a)!(c&&b==\"prototype\")&&d.call(a,b)&&f(b);for(c=h.length;b=h[--c];d.call(a,b)&&f(b));}}c(a,f)};if(!v(\"json-stringify\")){var L={92:\"\\\\\\\\\",34:'\\\\\"',8:\"\\\\b\",12:\"\\\\f\",\n10:\"\\\\n\",13:\"\\\\r\",9:\"\\\\t\"},u=function(a,f){return(\"000000\"+(f||0)).slice(-a)},G=function(a){var f='\"',b=0,d=a.length,h=d>10&&s,n;for(h&&(n=a.split(\"\"));b<d;b++){var e=a.charCodeAt(b);switch(e){case 8:case 9:case 10:case 12:case 13:case 34:case 92:f=f+L[e];break;default:if(e<32){f=f+(\"\\\\u00\"+u(2,e.toString(16)));break}f=f+(h?n[b]:s?a.charAt(b):a[b])}}return f+'\"'},E=function(a,b,c,d,h,n,e){var g=b[a],i,j,k,l,q,s,v,x,y;try{g=b[a]}catch(A){}if(typeof g==\"object\"&&g){i=m.call(g);if(i==\"[object Date]\"&&\n!p.call(g,\"toJSON\"))if(g>-1/0&&g<1/0){if(z){k=t(g/864E5);for(i=t(k/365.2425)+1970-1;z(i+1,0)<=k;i++);for(j=t((k-z(i,0))/30.42);z(i,j+1)<=k;j++);k=1+k-z(i,j);l=(g%864E5+864E5)%864E5;q=t(l/36E5)%24;s=t(l/6E4)%60;v=t(l/1E3)%60;l=l%1E3}else{i=g.getUTCFullYear();j=g.getUTCMonth();k=g.getUTCDate();q=g.getUTCHours();s=g.getUTCMinutes();v=g.getUTCSeconds();l=g.getUTCMilliseconds()}g=(i<=0||i>=1E4?(i<0?\"-\":\"+\")+u(6,i<0?-i:i):u(4,i))+\"-\"+u(2,j+1)+\"-\"+u(2,k)+\"T\"+u(2,q)+\":\"+u(2,s)+\":\"+u(2,v)+\".\"+u(3,l)+\"Z\"}else g=\nw;else if(typeof g.toJSON==\"function\"&&(i!=\"[object Number]\"&&i!=\"[object String]\"&&i!=\"[object Array]\"||p.call(g,\"toJSON\")))g=g.toJSON(a)}c&&(g=c.call(b,a,g));if(g===w)return\"null\";i=m.call(g);if(i==\"[object Boolean]\")return\"\"+g;if(i==\"[object Number]\")return g>-1/0&&g<1/0?\"\"+g:\"null\";if(i==\"[object String]\")return G(\"\"+g);if(typeof g==\"object\"){for(a=e.length;a--;)if(e[a]===g)throw TypeError();e.push(g);x=[];b=n;n=n+h;if(i==\"[object Array]\"){j=0;for(a=g.length;j<a;y||(y=o),j++){i=E(j,g,c,d,h,n,\ne);x.push(i===r?\"null\":i)}a=y?h?\"[\\n\"+n+x.join(\",\\n\"+n)+\"\\n\"+b+\"]\":\"[\"+x.join(\",\")+\"]\":\"[]\"}else{C(d||g,function(a){var b=E(a,g,c,d,h,n,e);b!==r&&x.push(G(a)+\":\"+(h?\" \":\"\")+b);y||(y=o)});a=y?h?\"{\\n\"+n+x.join(\",\\n\"+n)+\"\\n\"+b+\"}\":\"{\"+x.join(\",\")+\"}\":\"{}\"}e.pop();return a}};k.stringify=function(a,b,c){var d,h,j;if(typeof b==\"function\"||typeof b==\"object\"&&b)if(m.call(b)==\"[object Function]\")h=b;else if(m.call(b)==\"[object Array]\"){j={};for(var e=0,g=b.length,i;e<g;i=b[e++],(m.call(i)==\"[object String]\"||\nm.call(i)==\"[object Number]\")&&(j[i]=1));}if(c)if(m.call(c)==\"[object Number]\"){if((c=c-c%1)>0){d=\"\";for(c>10&&(c=10);d.length<c;d=d+\" \");}}else m.call(c)==\"[object String]\"&&(d=c.length<=10?c:c.slice(0,10));return E(\"\",(i={},i[\"\"]=a,i),h,j,d,\"\",[])}}if(!v(\"json-parse\")){var M=String.fromCharCode,N={92:\"\\\\\",34:'\"',47:\"/\",98:\"\\u0008\",116:\"\\t\",110:\"\\n\",102:\"\\u000c\",114:\"\\r\"},b,A,j=function(){b=A=w;throw SyntaxError();},q=function(){for(var a=A,f=a.length,c,d,h,k,e;b<f;){e=a.charCodeAt(b);switch(e){case 9:case 10:case 13:case 32:b++;\nbreak;case 123:case 125:case 91:case 93:case 58:case 44:c=s?a.charAt(b):a[b];b++;return c;case 34:c=\"@\";for(b++;b<f;){e=a.charCodeAt(b);if(e<32)j();else if(e==92){e=a.charCodeAt(++b);switch(e){case 92:case 34:case 47:case 98:case 116:case 110:case 102:case 114:c=c+N[e];b++;break;case 117:d=++b;for(h=b+4;b<h;b++){e=a.charCodeAt(b);e>=48&&e<=57||e>=97&&e<=102||e>=65&&e<=70||j()}c=c+M(\"0x\"+a.slice(d,b));break;default:j()}}else{if(e==34)break;e=a.charCodeAt(b);for(d=b;e>=32&&e!=92&&e!=34;)e=a.charCodeAt(++b);\nc=c+a.slice(d,b)}}if(a.charCodeAt(b)==34){b++;return c}j();default:d=b;if(e==45){k=o;e=a.charCodeAt(++b)}if(e>=48&&e<=57){for(e==48&&(e=a.charCodeAt(b+1),e>=48&&e<=57)&&j();b<f&&(e=a.charCodeAt(b),e>=48&&e<=57);b++);if(a.charCodeAt(b)==46){for(h=++b;h<f&&(e=a.charCodeAt(h),e>=48&&e<=57);h++);h==b&&j();b=h}e=a.charCodeAt(b);if(e==101||e==69){e=a.charCodeAt(++b);(e==43||e==45)&&b++;for(h=b;h<f&&(e=a.charCodeAt(h),e>=48&&e<=57);h++);h==b&&j();b=h}return+a.slice(d,b)}k&&j();if(a.slice(b,b+4)==\"true\"){b=\nb+4;return o}if(a.slice(b,b+5)==\"false\"){b=b+5;return false}if(a.slice(b,b+4)==\"null\"){b=b+4;return w}j()}}return\"$\"},F=function(a){var b,c;a==\"$\"&&j();if(typeof a==\"string\"){if((s?a.charAt(0):a[0])==\"@\")return a.slice(1);if(a==\"[\"){for(b=[];;c||(c=o)){a=q();if(a==\"]\")break;if(c)if(a==\",\"){a=q();a==\"]\"&&j()}else j();a==\",\"&&j();b.push(F(a))}return b}if(a==\"{\"){for(b={};;c||(c=o)){a=q();if(a==\"}\")break;if(c)if(a==\",\"){a=q();a==\"}\"&&j()}else j();(a==\",\"||typeof a!=\"string\"||(s?a.charAt(0):a[0])!=\"@\"||\nq()!=\":\")&&j();b[a.slice(1)]=F(q())}return b}j()}return a},I=function(a,b,c){c=H(a,b,c);c===r?delete a[b]:a[b]=c},H=function(a,b,c){var d=a[b],h;if(typeof d==\"object\"&&d)if(m.call(d)==\"[object Array]\")for(h=d.length;h--;)I(d,h,c);else C(d,function(a){I(d,a,c)});return c.call(a,b,d)};k.parse=function(a,f){var c,d;b=0;A=\"\"+a;c=F(q());q()!=\"$\"&&j();b=A=w;return f&&m.call(f)==\"[object Function]\"?H((d={},d[\"\"]=c,d),\"\",f):c}}}D&&define(function(){return k})})(this);return JSON;\n}());"
  },
  {
    "path": "src/util/encode/platform/json.js",
    "content": "// do nothing\n"
  },
  {
    "path": "src/util/encode/platform/json.patch.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n\t'base/platform'\n],function(_m,_p,_o,_f,_r){\n\t// ie8-\n\tNEJ.patch('TR<=5.0',['./3rd.json.js']);\n\n\t// ie6 json patch\n    NEJ.patch('TR==2.0',function(){\n\t    // eval for big string\n\t    JSON.parse = (function(){\n\t        // check save json string\n\t        // http://www.ietf.org/rfc/rfc4627.txt\n\t        var _isSafeJSON = function(_content){\n\t            return !(/[^,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t]/.test(\n\t                        _content.replace(/\"(\\\\.|[^\"\\\\])*\"/g,'')\n\t                    ));\n\t        };\n\t        return JSON.parse._$aop(function(_event){\n\t            var _str = _event.args[0]||'';\n\t            if (_str.length>=500000){  // &&_isSafeJSON(_str)\n\t                _event.stopped = !0;\n\t                _event.value = eval('('+_str+')');\n\t            }\n\t        });\n\t    })();\n\t});\n\n\treturn JSON;\n});"
  },
  {
    "path": "src/util/encode/sha.md5.js",
    "content": "// link to util/encode/md5 for compatible\n// use util/encode/md5 for new project\nNEJ.define(['./md5.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/encode/test/base64.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>base64测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit base64 test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n \t\t<script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./base64.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/util/encode/test/base64.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"base64\");\n    var p = NEJ.P('nej.u');\n    //开始单元测试\n    test('base64编码解码', function() {\n        var _strList = ['a','null','function','error','return','switch','if','!0',\n        'UNdefined','NULL','Function','ERROR','return 1'];\n        stop();\n        for(var i = 0; i < _strList.length; i++){\n            var _str = _strList[i];\n            var _str2b64 = p._$str2b64(_str);\n            var _b642str = p._$b642str(_str2b64);\n            equal(_str,_b642str,'编码，反编码，结果一致');\n            start();\n        }\n    });\n    \n    test('base64中文编码解码', function() {\n        var _strList = ['中文','中文 空格','中文　全角空格'];\n        stop();\n        for(var i = 0; i < _strList.length; i++){\n            var _str = _strList[i];\n            var _str2b64 = p._$str2b64(_str);\n            var _b642str = p._$b642str(_str2b64);\n            equal(_str,_b642str,'中文编码，反编码，结果一致');\n            start();\n        }\n    });\n    \n    test('base64带特殊符号编码解码', function() {\n        var _strList = [',:\"\\\\[]{}'];\n        stop();\n        for(var i = 0; i < _strList.length; i++){\n            var _str = _strList[i];\n            var _str2b64 = p._$str2b64(_str);\n            var _b642str = p._$b642str(_str2b64);\n            equal(_str,_b642str,'带特殊符号编码，反编码，结果一致');\n            start();\n        }\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}base64.test.js',\n    ['{lib}util/encode/base64.js'],f);\n});\n  "
  },
  {
    "path": "src/util/es/array.js",
    "content": "/*\n * ------------------------------------------\n * ES规范数组兼容实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/**\n * Array对象\n * @external Array\n */\nNEJ.define([\n    '{platform}array.js'\n],function(_h){\n    // do nothing\n    /**\n     * 判断参数是否数组\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/es/array'\n     * ],function(){\n     *     // 返回true\n     *     var is = Array.isArray([]);\n     * });\n     * ```\n     * \n     * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.3.2\n     * @method external:Array.isArray\n     * @param  {Variable} arg0 - 数据\n     * @return {Boolean}         是否数组\n     */\n    \n    /**\n     * 反转顺序，修改原数组\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/es/array'\n     * ],function(){\n     *     var arr = [1,2,3,4];\n     *     // 反转数组\n     *     arr.reverse();\n     *     // arr变成[4,3,2,1]\n     * });\n     * ```\n     * \n     * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.8\n     * @method external:Array#reverse\n     * @return {Array} 数组\n     */\n    \n    /**\n     * 查找第一个符合条件的元素的索引值，匹配规则为全等匹配\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/es/array'\n     * ],function(){\n     *     var arr = [1,2,3,4];\n     *     // 返回1\n     *     var index = arr.indexOf(2);\n     *     // 返回-1\n     *     var index = arr.indexOf(7);\n     * });\n     * ```\n     * \n     * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.14\n     * @method external:Array#indexOf\n     * @param  {Variable} arg0 - 要搜索的元素\n     * @param  {Number}   arg1 - 起始索引，默认从0开始，负数表示从length-begin的位置开始搜索\n     * @return {Number}          符合条件的元素索引，没有找到返回-1\n     */\n    \n    /**\n     * 查找最后一个符合条件的元素的索引值，匹配规则为全等匹配\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/es/array'\n     * ],function(){\n     *     var arr = [1,2,3,4];\n     *     // 返回1\n     *     var index = arr.lastIndexOf(2);\n     *     // 返回-1\n     *     var index = arr.lastIndexOf(7);\n     * });\n     * ```\n     * \n     * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.15\n     * @method external:Array#lastIndexOf\n     * @param  {Variable} arg0 - 要搜索的元素\n     * @param  {Number}   arg1 - 搜索结束位置，默认为数组尾部，负数表示在length-end的位置结束\n     * @return {Number}          符合条件的元素索引，没有找到返回-1\n     */\n    \n    /**\n     * 检查数组所有元素是否满足指定条件\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/es/array'\n     * ],function(){\n     *     var arr = [1,2,3,4];\n     *     // 验证所有元素是否都是非NaN，返回true\n     *     var is = arr.every(function(item,index,array){\n     *         return !isNaN(item);\n     *     });\n     * });\n     * ```\n     * \n     * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.16\n     * @method external:Array#every\n     * @param  {Function} arg0 - 验证函数\n     * @param  {Object}   arg1 - 验证函数需要保持一致的对象，null表示window对象\n     * @return {Boolean}         是否所有元素都满足条件\n     */\n    \n    /**\n     * 检查数组中是否有元素满足指定条件\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/es/array'\n     * ],function(){\n     *     var arr = [1,2,3,4,'5'];\n     *     // 验证是否含字符串，返回true\n     *     var is = arr.some(function(item,index,array){\n     *         return typeof item === 'string';\n     *     });\n     * });\n     * ```\n     * \n     * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.17\n     * @method external:Array#some\n     * @param  {Function} arg0 - 验证函数\n     * @param  {Object}   arg1 - 验证函数需要保持一致的对象，null表示window对象\n     * @return {Boolean}         是否有元素满足指定条件\n     */\n    \n    /**\n     * 遍历数组所有元素，并执行指定函数\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/es/array'\n     * ],function(){\n     *     var arr = [1,2,3,4,'5'];\n     *     // 遍历数组\n     *     arr.forEach(function(item,index,array){\n     *         console.log(item);\n     *     });\n     * });\n     * ```\n     * \n     * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18\n     * @method external:Array#forEach\n     * @param  {Function} arg0 - 执行函数\n     * @param  {Object}   arg1 - 执行函数需要保持一致的对象，null表示window对象\n     * @return {Void}\n     */\n    \n    /**\n     * 对数组中所有元素使用处理函数生成新元素形成的新数组\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/es/array'\n     * ],function(){\n     *     var arr = [1,2,3,4];\n     *     // 生成对象 {0:'d-1',1:'d-2',2:'d-3',3:'d-4'}\n     *     var map = arr.map(function(item,index,array){\n     *         return 'd-'+item;\n     *     });\n     * });\n     * ```\n     * \n     * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.19\n     * @method external:Array#map\n     * @param  {Function} arg0 - 处理函数\n     * @param  {Object}   arg1 - 处理函数需要保持一致的对象，null表示window对象\n     * @return {Array}           根据处理函数生成的新的数组\n     */\n    \n    /**\n     * 过滤不符合条件的元素，返回符合条件的所有元素形成的新数组\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/es/array'\n     * ],function(){\n     *     var arr = [1,2,3,4];\n     *     // 生成新数组 [1,2]\n     *     var brr = arr.filter(function(item,index,array){\n     *         return item<=2;\n     *     });\n     * });\n     * ```\n     * \n     * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.20\n     * @method external:Array#filter\n     * @param  {Function} arg0 - 验证函数\n     * @param  {Object}   arg1 - 验证函数需要保持一致的对象，null表示window对象\n     * @return {Array}           符合验证规则的元素形成的新数组\n     */\n    \n    /**\n     * 从左到右根据处理函数计算数组中各元素的值\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/es/array'\n     * ],function(){\n     *     var arr = [1,2,3,4];\n     *     // 计算数组元素总和 1+2+3+4，返回10\n     *     var sum = arr.reduce(function(value,item,index,array){\n     *         return value+item;\n     *     });\n     * });\n     * ```\n     * \n     * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.21\n     * @method external:Array#reduce\n     * @param  {Function} arg0 - 处理函数\n     * @param  {Variable} arg1 - 初始值\n     * @return {Variable}        计算结果\n     */\n    \n    /**\n     * 从右到左根据处理函数计算数组中各元素的值\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/es/array'\n     * ],function(){\n     *     var arr = [1,2,3,4];\n     *     // 计算数组元素总和 4+3+2+1，返回10\n     *     var sum = arr.reduceRight(function(value,item,index,array){\n     *         return value+item;\n     *     });\n     * });\n     * ```\n     * \n     * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.22\n     * @method external:Array#reduceRight\n     * @param  {Function} arg0 - 处理函数\n     * @param  {Variable} arg1 - 初始值\n     * @return {Variable}        计算结果\n     */\n});\n"
  },
  {
    "path": "src/util/es/demo/array.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - ES-Array兼容接口</title>\n    <meta charset=\"utf-8\" />\n  </head>\n  <body>\n    \n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            'util/es/array'\n        ],function(){\n            var sum = [1,2,3,4].reduce(function(value,item,index,array){\n                return value+item;\n            });\n            alert(sum);\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/es/platform/array.js",
    "content": ""
  },
  {
    "path": "src/util/es/platform/array.patch.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    './array.js',\n    'base/platform'\n],function(_h,_m,_p,_o,_f,_r){\n    // TR 2.0 - IE 6\n    // TR 3.0 - IE 7\n    // TR 4.0 - IE 8\n    // TR 5.0 - IE 9\n    // TR 6.0 - IE 10\n    // TR 7.0 - IE 11\n    \n    // for ie8-\n    NEJ.patch('TR<=4.0',function(){\n        var _pro = Array.prototype;\n        /*\n         * 判断是否函数\n         * @return {Boolean} 是否函数\n         */\n        var _isFunction = function(_arg){\n            return '[object function]' == _o.toString.call(_arg).toLowerCase();\n        };\n        /**\n         * 判断参数是否数组\n         * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.3.2\n         * @param  {Variable} 数据\n         * @return {Boolean}  是否数组\n         */\n        Array.isArray = function(_arg){\n            return \"[object array]\" === _o.toString.call(_arg).toLowerCase();\n        };\n        /**\n         * 查找第一个符合条件的元素的索引值，匹配规则为全等匹配\n         * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.14\n         * @param  {Variable} 要搜索的元素\n         * @param  {Number}   起始索引，默认从0开始，负数表示从length-begin的位置开始搜索\n         * @return {Number}   符合条件的元素索引，没有找到返回-1\n         */\n        _pro.indexOf = function(_match,_beg){\n            var _index = parseInt(_beg)||0;\n            if (_index<0){\n                _index = Math.max(0,this.length+_index);\n            }\n            for(var l=this.length;_index<l;_index++){\n                if ((_index in this)&&_match===this[_index])\n                    return _index;\n            }\n            return -1;\n        };\n        /**\n         * 查找最后一个符合条件的元素的索引值，匹配规则为全等匹配\n         * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.15\n         * @param  {Variable} 要搜索的元素\n         * @param  {Number}   搜索结束位置，默认为数组尾部，负数表示在length-end的位置结束\n         * @return {Number}   符合条件的元素索引，没有找到返回-1\n         */\n        _pro.lastIndexOf = function(_match,_end){\n            var _index = this.length-1;\n            _end = parseInt(_end);\n            if (!isNaN(_end)){\n                _index = _end;\n                if (_index<0){\n                    _index = this.length+_index;\n                }\n            }\n            for(;_index>=0;_index--){\n                if ((_index in this)&&_match===this[_index])\n                    return _index;\n            }\n            return -1;\n        };\n        /**\n         * 检查数组所有元素是否满足指定条件\n         * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.16\n         * @param  {Function} 验证函数\n         * @param  {Object}   验证函数需要保持一致的对象，null表示window对象\n         * @return {Boolean}  是否所有元素都满足条件\n         */\n        _pro.every = function(_callback,_this){\n            if (!_isFunction(_callback)){\n                throw new Error(_callback+' is not a function');\n            }\n            for(var i=0,l=this.length;i<l;i++){\n                if ((i in this)&&!_callback.call(_this,this[i],i,this))\n                    return !1;\n            }\n            return !0;\n        };\n        /**\n         * 检查数组中是否有元素满足指定条件\n         * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.17\n         * @param  {Function} 验证函数\n         * @param  {Object}   验证函数需要保持一致的对象，null表示window对象\n         * @return {Boolean}  是否有元素满足指定条件\n         */\n        _pro.some = function(_callback,_this){\n            if (!_isFunction(_callback)){\n                throw new Error(_callback+' is not a function');\n            }\n            for(var i=0,l=this.length;i<l;i++){\n                if ((i in this)&&_callback.call(_this,this[i],i,this))\n                    return !0;\n            }\n            return !1;\n        };\n        /**\n         * 遍历数组所有元素，并执行制定函数\n         * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18\n         * @param  {Function} 执行函数\n         * @param  {Object}   执行函数需要保持一致的对象，null表示window对象\n         * @return {Void}\n         */\n        _pro.forEach = function(_callback,_this){\n            if (!_isFunction(_callback)){\n                throw new Error(_callback+' is not a function');\n            }\n            for(var i=0,l=this.length;i<l;i++){\n                if (i in this){\n                    _callback.call(_this,this[i],i,this);\n                }\n            }\n        };\n        /**\n         * 对数组中所有元素使用处理函数生成新元素形成的新数组\n         * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.19\n         * @param  {Function} 处理函数\n         * @param  {Object}   处理函数需要保持一致的对象，null表示window对象\n         * @return {Array}    根据处理函数生成的新的数组\n         */\n        _pro.map = function(_callback,_this){\n            if (!_isFunction(_callback)){\n                throw new Error(_callback+' is not a function');\n            }\n            var _result = new Array(this.length);\n            for(var i=0,l=this.length;i<l;i++){\n                if (i in this){\n                    _result[i] = _callback.call(_this,this[i],i,this);\n                }\n            }\n            return _result;\n        };\n        /**\n         * 过滤不符合条件的元素，返回符合条件的所有元素形成的新数组\n         * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.20\n         * @param  {Function} 验证函数\n         * @param  {Object}   验证函数需要保持一致的对象，null表示window对象\n         * @return {Array}    符合验证规则的元素形成的新数组\n         */\n        _pro.filter = function(_callback,_this){\n            if (!_isFunction(_callback)){\n                throw new Error(_callback+' is not a function');\n            }\n            var _result = [];\n            for(var i=0,l=this.length;i<l;i++){\n                if ((i in this)&&_callback.call(_this,this[i],i,this)){\n                    _result.push(this[i]);\n                }\n            }\n            return _result;\n        };\n        /**\n         * 从左到右根据处理函数计算数组中各元素的值\n         * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.21\n         * @param  {Function} 处理函数\n         * @param  {Variable} 初始值\n         * @return {Variable} 计算结果\n         */\n        _pro.reduce = function(_callback,_value){\n            if (!_isFunction(_callback)){\n                throw new Error(_callback+' is not a function');\n            }\n            var _isset = arguments.length>1;\n            for(var i=0,l=this.length;i<l;i++){\n                if (!(i in this)) continue;\n                if (_isset){\n                    _value = _callback(_value,this[i],i,this);\n                }else{\n                    _isset = !0;\n                    _value = this[i];\n                }\n            }\n            if (!_isset){\n              throw new Error('Reduce of empty array with no initial value');\n            }\n            return _value;\n        };\n        /**\n         * 从右到左根据处理函数计算数组中各元素的值\n         * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.22\n         * @param  {Function} 处理函数\n         * @param  {Variable} 初始值\n         * @return {Variable} 计算结果\n         */\n        _pro.reduceRight = function(_callback,_value){\n            if (!_isFunction(_callback)){\n                throw new Error(_callback+' is not a function');\n            }\n            var _isset = arguments.length>1;\n            for(var i=this.length-1;i>=0;i--){\n                if (!(i in this)) continue;\n                if (_isset){\n                    _value = _callback(_value,this[i],i,this);\n                }else{\n                    _isset = !0;\n                    _value = this[i];\n                }\n            }\n            if (!_isset){\n              throw new Error('Reduce of empty array with no initial value');\n            }\n            return _value;\n        };\n    });\n    \n    return _h;\n});\n"
  },
  {
    "path": "src/util/event/esb.js",
    "content": "/*\n * ------------------------------------------\n * 消息总线实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/event/esb */\nNEJ.define([\n    'base/klass',\n    'util/event'\n],function(\n    k, t,\n    exports, pro\n){\n    /**\n     * 消息总线\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/event/esb'\n     * ],function(esb){\n     *      // 添加事件，新加的事件不会覆盖原同名事件\n     *      esb._$addEvent(\n     *          'onxxx', function(event){\n     *              // TODO\n     *              // 阻止后续逻辑\n     *              // esb._$stop(event);\n     *              // 判断事件是否被阻止\n     *              // esb._$isStopped(event);\n     *          }\n     *      );\n     *      // 设置事件，新加的事件覆盖原同名事件\n     *      esb._$setEvent(\n     *          'onxxx', function(event){\n     *              // TODO\n     *          }\n     *      );\n     *      // 删除事件，注意这里的 eventHandler 引用必须跟添加时一致\n     *      esb._$delEvent(\n     *          'onxxx', eventHandler\n     *      );\n     *      // 调度事件\n     *      esb._$dispatchEvent(\n     *          'onxxx',{\n     *              a:'aaaa',\n     *              b:'bbbbb'\n     *          }\n     *      )\n     * });\n     * ```\n     *\n     * @class    module:util/event/esb.ESB\n     * @extends  module:util/event/esb._$$EventTarget\n     *\n     * @param    {Object} config  - 可选配置参数\n     */\n    var ESB = k._$klass();\n    pro = ESB._$extend(t._$$EventTarget);\n\n    /**\n     * 阻止事件\n     *\n     * @method module:util/event/esb.ESB#_$isStopped\n     * @param  {String} arg0 - 事件对象\n     * @return {Void}\n     */\n    pro._$stop = function(event){\n        (event||{}).__stopped__ = !0;\n    };\n\n    /**\n     * 判断事件是否被阻止\n     *\n     * @method module:util/event/esb.ESB#_$isStopped\n     * @param  {String} arg0 - 事件对象\n     * @return {Void}\n     */\n    pro._$isStopped = function(event){\n        return !!(event||{}).__stopped__;\n    };\n\n    // return esb instance\n    return ESB._$allocate();\n});"
  },
  {
    "path": "src/util/event/event.js",
    "content": "/*\n * ------------------------------------------\n * 自定义事件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/event/event */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'base/util',\n    'util/event'\n],function(NEJ,_k,_e,_v,_u,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 自定义事件封装对象，封装的事件支持通过事件相关接口进行添加、删除等操作\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/event'\n     *     'util/event'\n     * ],function(_v,_t){\n     *     // 支持自定义事件\n     *     _t._$$CustomEvent._$allocate({\n     *         element:window,\n     *         event:'ok'\n     *     });\n     * \n     *     // 添加自定义事件 \n     *     _v._$addEvent(window,'ok',function(){alert(0);});\n     *     _v._$addEvent(window,'ok',function(){alert(1);});\n     *     \n     *     // 删除自定义事件\n     *     _v._$delEvent(window,'ok',function(){alert(0);});\n     *     _v._$clearEvent(window,'ok');\n     *     \n     *     // 触发自定义事件\n     *     window.onok({a:'aaaaa'});\n     *     _v._$dispatchEvent(window,'ok',{a:'aaaaa'});\n     * });\n     * ```\n     * \n     * @class    module:util/event/event._$$CustomEvent\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object}       config  - 可选配置参数\n     * @property {String|Node}  element - 事件关联节点ID或者对象，默认为window对象\n     * @property {String|Array} event   - 事件名称或者名称列表\n     */\n    /** \n     * 初始化时触发事件\n     * \n     * @event module:util/event/event._$$CustomEvent#oninit\n     * @param {Object} event - 事件信息\n     */\n    /** \n     * 事件调度前触发事件\n     * \n     * @event    module:util/event/event._$$CustomEvent#ondispatch\n     * @param    {Object} event - 事件信息\n     * @property {String} type  - 事件类型\n     */\n    /**\n     * 添加事件时触发事件\n     * \n     * @event    module:util/event/event._$$CustomEvent#oneventadd\n     * @param    {Object}   event    - 事件信息\n     * @property {String}   type     - 事件类型\n     * @property {Function} listener - 事件执行函数\n     */\n    _p._$$CustomEvent = _k._$klass();\n    _pro = _p._$$CustomEvent._$extend(_t._$$EventTarget);\n    /**\n     * 控件初始化\n     * \n     * @protected\n     * @method module:util/event/event._$$CustomEvent#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        // onxxx - event entry handler\n        //   xxx - event callback handler list\n        this.__cache = {};\n        this.__super();\n    };\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/event/event._$$CustomEvent#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__element = _e._$get(_options.element)||window;\n        // init event\n        this.__doEventInit(_options.event);\n        this.__doEventAPIEnhance();\n        this._$dispatchEvent('oninit');\n    };\n    /**\n     * 销毁控件\n     * \n     * @protected\n     * @method module:util/event/event._$$CustomEvent#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = (function(){\n        var _doClear = function(_value,_key,_map){\n            if (!_u._$isArray(_value)){\n                _u._$safeDelete(this.__element,_key);\n            }\n            delete _map[_key];\n        };\n        return function(){\n            this.__super();\n            // clear cache\n            _u._$loop(\n                this.__cache,_doClear,this\n            );\n            delete this.__element;\n        };\n    })();\n    /**\n     * 判断是否需要代理事件\n     * \n     * @protected\n     * @method module:util/event/event._$$CustomEvent#__isDelegate\n     * @param  {String|Node} arg0 - 节点\n     * @param  {String}      arg1 - 事件\n     * @return {Boolean}            是否需要代理事件\n     */\n    _pro.__isDelegate = function(_element,_type){\n        _element = _e._$get(_element);\n        return _element===this.__element&&\n               (!_type||!!this.__cache['on'+_type]);\n    };\n    /**\n     * 初始化事件\n     * \n     * @protected\n     * @method module:util/event/event._$$CustomEvent#__doEventInit\n     * @param  {String} arg0 - 事件名称\n     * @return {Void}\n     */\n    _pro.__doEventInit = function(_event){\n        if (_u._$isString(_event)){\n            var _name = 'on'+_event;\n            if (!this.__cache[_name]){\n                this.__cache[_name] = \n                    this.__doEventDispatch.\n                        _$bind(this,_event);\n            }\n            this.__doEventBind(_event); \n            return;\n        }\n        if (_u._$isArray(_event)){\n            _u._$forEach(\n                _event,this.__doEventInit,this\n            );\n        }\n    };\n    /**\n     * 绑定事件\n     * \n     * @protected\n     * @method module:util/event/event._$$CustomEvent#__doEventBind\n     * @param  {String} arg0 - 事件名称\n     * @return {Void}\n     */\n    _pro.__doEventBind = function(_type){\n        var _event = 'on'+_type,\n            _handler = this.__element[_event],\n            _handler1 = this.__cache[_event];\n        if (_handler!=_handler1){\n            this.__doEventDelete(_type);\n            if (!!_handler&&_handler!=_f){\n                this.__doEventAdd(_type,_handler);\n            }\n            this.__element[_event] = _handler1;\n        }\n    };\n    /**\n     * 添加事件\n     * \n     * protected\n     * @method module:util/event/event._$$CustomEvent#__doEventAdd\n     * @param  {String}   arg0 - 事件名称\n     * @param  {Function} arg1 - 事件回调\n     * @return {Void}\n     */\n    _pro.__doEventAdd = function(_type,_handler,_front){\n        var _list = this.__cache[_type];\n        if (!_list){\n            _list = [];\n            this.__cache[_type] = _list;\n        }\n        if (_u._$isFunction(_handler)){\n            !_front ? _list.push(_handler)\n                    : _list.unshift(_handler);\n        } \n    };\n    /**\n     * 删除事件\n     * \n     * protected\n     * @method module:util/event/event._$$CustomEvent#__doEventDelete\n     * @param  {String}   arg0 - 事件名称\n     * @param  {Function} arg1 - 事件回调\n     * @return {Void}\n     */\n    _pro.__doEventDelete = function(_type,_handler){\n        var _list = this.__cache[_type];\n        if (!_list||!_list.length) return;\n        // clear all event handler\n        if (!_handler){\n            delete this.__cache[_type];\n            return;\n        }\n        // delete one event handler\n        _u._$reverseEach(\n            _list,function(_value,_index,_xlist){\n                if (_handler===_value){\n                    _xlist.splice(_index,1);\n                    return !0;\n                }\n            }\n        );\n    };\n    /**\n     * 事件调度\n     * \n     * protected\n     * @method module:util/event/event._$$CustomEvent#__doEventDispatch\n     * @param  {String} arg0 - 事件名称\n     * @param  {Object} arg1 - 事件对象\n     * @return {Void}\n     */\n    _pro.__doEventDispatch = function(_type,_event){\n        _event = _event||{noargs:!0};\n        if (_event==_o){\n            _event = {};\n        }\n        _event.type = _type;\n        this._$dispatchEvent('ondispatch',_event);\n        if (!!_event.stopped) return;\n        _u._$forEach(\n            this.__cache[_type],function(_handler){\n                if (DEBUG){\n                    _handler(_event);\n                }else{\n                    try{\n                        _handler(_event);\n                    }catch(ex){\n                        // ignore\n                        console.error(ex.message);\n                        console.error(ex.stack);\n                    }\n                }\n            }\n        );\n    };\n    /**\n     * 增强事件操作API\n     * \n     * protected\n     * @method module:util/event/event._$$CustomEvent#__doEventAPIEnhance\n     * @return {Void}\n     */\n    _pro.__doEventAPIEnhance = (function(){\n        var _doAddEvent = function(_event){\n            var _args = _event.args,\n                _type = _args[1].toLowerCase();\n            if (this.__isDelegate(_args[0],_type)){\n                _event.stopped = !0;\n                this.__doEventBind(_type);\n                this.__doEventAdd(_type,_args[2],_args[3]);\n                this._$dispatchEvent('oneventadd',{\n                    type:_type,\n                    listener:_args[2]\n                });\n            }\n        };\n        var _doDelEvent = function(_event){\n            var _args = _event.args,\n                _type = _args[1].toLowerCase();\n            if (this.__isDelegate(_args[0],_type)){\n                _event.stopped = !0;\n                this.__doEventDelete(_type,_args[2]);\n            }\n        };\n        var _doClearEvent = function(_event){\n            var _args = _event.args,\n                _type = (_args[1]||'').toLowerCase();\n            if (this.__isDelegate(_args[0])){\n                if (!!_type){\n                    this.__doEventDelete(_type);\n                    return;\n                }\n                _u._$loop(\n                    this.__cache,function(_value,_key){\n                        if (_u._$isArray(_value)){\n                            this.__doEventDelete(_key);\n                        }\n                    },this\n                );\n            }\n        };\n        var _doDispatchEvent = function(_event){\n            var _args = _event.args,\n                _type = _args[1].toLowerCase();\n            if (this.__isDelegate(_args[0],_type)){\n                _event.stopped = !0;\n                _args[0]['on'+_type].apply(_args[0],_args.slice(2));\n            }\n        };\n        return function(){\n            // void multi-enhance\n            if (!!this.__enhanced){\n                return;\n            }\n            // enhance event api\n            this.__enhanced = true;\n            _v._$addEvent = _v._$addEvent._$aop(_doAddEvent._$bind(this));\n            _v._$delEvent = _v._$delEvent._$aop(_doDelEvent._$bind(this));\n            _v._$clearEvent = _v._$clearEvent._$aop(_doClearEvent._$bind(this));\n            _v._$dispatchEvent = _v._$dispatchEvent._$aop(_doDispatchEvent._$bind(this));\n            \n            if (CMPT){\n                NEJ.copy(NEJ.P('nej.v'),_v);\n            }\n        };\n    })();\n    \n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/event.js",
    "content": "/*\n * ------------------------------------------\n * @file     控件基类\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/event */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/event',\n    'base/util'\n],function(NEJ,_k,_v,_u,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 控件基类，主要实现以下功能：\n     * * 对事件驱动编程模型的支持\n     * * 对控件通用行为及业务逻辑的抽象\n     * \n     * ```javascript\n     *   NEJ.define([\n     *       'base/klass',\n     *       'util/event'\n     *   ],function(_k,_t,_p,_o,_f,_r){\n     *       // 自定义一个控件及使用、回收的流程\n     *       var _pro;\n     *   \n     *       // 第一步\n     *       // 定义控件类，从父类继承\n     *       _p._$$Widget = _k._$klass();\n     *       _pro = _p._$$Widget._$extend(_t._$$EventTarget);\n     *   \n     *       // 第二步\n     *       // 重写控件初始化业务逻辑\n     *       _pro.__init = function(_options){\n     *           // _options - 配置参数信息\n     *           //            初始化时一般不对该参数做处理\n     *           // 调用父类初始化业务逻辑\n     *           this.__super(_options);\n     *           // TODO something\n     *       };\n     *   \n     *       // 第三步\n     *       // 重写控件重置业务逻辑\n     *       _pro.__reset = function(_options){\n     *           // _options - 配置参数信息\n     *           //            此处重置控件配置信息\n     *           // 调用父类重置业务逻辑\n     *           this.__super(_options);\n     *           // TODO something\n     *       };\n     *   \n     *       // 第四步\n     *       // 重写控件回收业务逻辑\n     *       _pro.__destroy = function __destroy(){\n     *           // 调用父类回收业务逻辑\n     *           this.__super();\n     *           // TODO something\n     *       };\n     *   \n     *       // 第五步\n     *       // 使用控件\n     *       var _widget = _p._$$Widget._$allocate({\n     *           a:'aaaaaaaaaaa',\n     *           b:'bbbbbbbbbbbbb',\n     *           c:'ccccccccccccccc'\n     *       });\n     *   \n     *       // 第六步\n     *       // 回收控件\n     *       _widget = _widget._$recycle();\n     *       // 也可以使用以下方式回收，建议使用上面的回收方式\n     *       _widget = _p._$$Widget._$recycle(_widget);\n     *   });\n     * ```\n     * \n     * @class module:util/event._$$EventTarget\n     * @param {Object} config - 配置参数，根据控件实际情况提供配置参数支持\n     */\n    /** \n     * 控件回收前触发事件，控件在具体实现时如需触发回收前的事件\n     * \n     * ```javascript\n     *   // 重写控件回收业务逻辑触发onbeforerecycle事件\n     *   _pro.__destroy = function(){\n     *       this._$dispatchEvent('onbeforerecycle');\n     *       // 调用父类回收业务逻辑\n     *       this.__super();\n     *       // TODO something\n     *   };\n     * \n     *   // 监测onbeforerecycle事件\n     *   var _widget = _p._$$Widget._$allocate({\n     *       onbeforerecycle:function(_event){\n     *           // TODO something\n     *       }\n     *   });\n     * ```\n     * \n     * @event module:util/event._$$EventTarget#onbeforerecycle\n     * @param {Object} event - 事件触发信息\n     */\n    /**\n     * 控件回收后触发事件，控件在具体实现时如需触发回收后的事件\n     * \n     * ```javascript\n     *   // 重写控件回收业务逻辑触发onbeforerecycle事件\n     *   _pro.__destroy = function(){\n     *       // 调用父类回收业务逻辑\n     *       this.__super();\n     *       // TODO something\n     *       this._$dispatchEvent('onaftercycle');\n     *   };\n     *   \n     *   // 监测onaftercycle事件\n     *   var _widget = _p._$$Widget._$allocate({\n     *       onaftercycle:function(_event){\n     *           // TODO something\n     *       }\n     *   });\n     * ```\n     * \n     * @event module:util/event._$$EventTarget#onaftercycle\n     * @param {Object} event - 事件触发信息\n     */\n    _p._$$EventTarget = _k._$klass();\n    _pro = _p._$$EventTarget.prototype;\n    /**\n     * 控件分配，NEJ框架提供的所有控件统一使用分配和回收机制，\n     * 分配空间时会优先考虑使用前面回收的同种控件，只有在没有可用控件的情况下才会实例化新的控件\n     * \n     * ```javascript\n     *   // 分配一个控件\n     *   var _widget = _p._$$Widget._$allocate({\n     *       conf0:'aaaaaaa',\n     *       conf1:'bbbbbbbbbbbbb',\n     *       onxxx:function(){\n     *           // TODO something\n     *       }\n     *   });\n     * ```\n     * \n     * @method module:util/event._$$EventTarget._$allocate\n     * @see    module:util/event._$$EventTarget._$getInstance\n     * @see    module:util/event._$$EventTarget._$getInstanceWithReset\n     * @param  {Object}  arg0 - 配置参数，根据控件实际情况提供配置参数支持\n     * @return {module:util/event._$$EventTarget} 控件实例\n     */\n    _p._$$EventTarget._$allocate = function(_options){\n        _options = _options||{};\n        var _instance = !!this.__pool\n                        &&this.__pool.shift();\n        if (!_instance){\n            _instance = new this(_options);\n            this.__inst__ = (this.__inst__||0)+1;\n        }\n        // reset instance, flag first\n        _instance.__reset(_options);\n        return _instance;\n    };\n    /**\n     * 控件回收，NEJ框架提供的所有控件统一使用分配和回收机制，\n     * 如果提供的实例非当前类的实例则自动调整为输入实例的类来回收此实例\n     * \n     * ```javascript\n     *   // 回收前面分配的实例有两种方式\n     *   // 如果不能确定实例的构造类，则可以直接使用实例的回收接口\n     *   _widget._$recycle();\n     *   // 如果可以确定实例的构造类，则可以使用构造类的静态回收接口\n     *   _p._$$Widget._$recycle(_widget);\n     *   // 如果回收多个实例则使用构造类的静态回收接口\n     *   _p._$$Widget._$recycle([_widget0,_widget1]);\n     * ```\n     * \n     * @method module:util/event._$$EventTarget._$recycle\n     * @param  {module:util/event._$$EventTarget|module:util/event._$$EventTarget[]} arg0 - 待回收实例或者实例列表\n     * @return {Void}\n     */\n    _p._$$EventTarget._$recycle = (function(){\n        var _doRecycle = function(_item,_index,_list){\n            _item._$recycle();\n            _list.splice(_index,1);\n        };\n        return function(_instance){\n            if (!_instance) return null;\n            if (!_u._$isArray(_instance)){\n                // instance is not instanceof class\n                if (!(_instance instanceof this)){\n                    // use constructor recycle instance\n                    var _class = _instance.constructor;\n                    if (!!_class._$recycle){\n                        _class._$recycle(_instance);\n                    }\n                    return null;\n                }\n                // delete singleton instance\n                if (_instance==this.__instance){\n                    delete this.__instance;\n                }\n                if (_instance==this.__inctanse){\n                    delete this.__inctanse;\n                }\n                // do recycle\n                _instance.__destroy();\n                // recycle instance\n                if (!this.__pool){\n                    this.__pool = [];\n                } \n                if (_u._$indexOf(this.__pool,_instance)<0){\n                    this.__pool.push(_instance);\n                }\n                return null;\n            }\n            // recycle instance array\n            _u._$reverseEach(_instance,_doRecycle,this);\n        };\n    })();\n    /**\n     * 取控件实例（单例），如果控件指明了为单例模式，\n     * 则项目中使用该控件时统一使用此接口获取控件实例，使用方式同_$allocate\n     * \n     * ```javascript\n     *   // 取控件单例，确保在第一次取单例时输入所有配置参数\n     *   var _widget = _p._$$Widget._$getInstance({\n     *       conf0:'aaaaaaa',\n     *       conf1:'bbbbbbbbbbbbb',\n     *       onxxx:function(){\n     *           // TODO something\n     *       }\n     *   });\n     *   \n     *   // 后续取单例忽略配置参数\n     *   var _widget1 = _p._$$Widget._$getInstance({\n     *       conf0:'bbbbb'  // <-- 如果单例已生成，则这里的配置信息不会生效\n     *   });\n     * \n     *   // 等价于如下调用\n     *   var _widget2 = _p._$$Widget._$getInstance();\n     * ```\n     * \n     * @method module:util/event._$$EventTarget._$getInstance\n     * @see    module:util/event._$$EventTarget._$getInstanceWithReset\n     * @see    module:util/event._$$EventTarget._$allocate\n     * @param  {Object}  arg0 - 配置参数，根据控件实际情况提供配置参数支持\n     * @return {module:util/event._$$EventTarget} 控件实例\n     */\n    _p._$$EventTarget._$getInstance = function(_options){\n        if (!this.__instance){\n            this.__instance = this._$allocate(_options);\n        }\n        return this.__instance;\n    };\n    /**\n     * 取控件实例（单例），如果控件指明了为单例模式，\n     * 则项目中使用该控件时统一使用此接口获取控件实例，使用方式同_$getInstance，\n     * 该接口同_$getInstance接口的主要区别在于输入的配置参数是否在每次调用接口时都重置\n     * \n     * ```javascript\n     *   // 取控件单例，确保在第一次取单例时输入所有配置参数\n     *   var _widget = _p._$$Widget._$getInstanceWithReset({\n     *       conf0:'aaaaaaa',\n     *       conf1:'bbbbbbbbbbbbb',\n     *       onxxx:function(){\n     *           // TODO something\n     *       }\n     *   });\n     *   \n     *   // 后续取单例使用新的配置参数\n     *   var _widget1 = _p._$$Widget._$getInstanceWithReset({\n     *       conf0:'bbbbb'  // <-- 如果单例已生成，则重置这里的配置信息\n     *   });\n     * ```\n     * \n     * @method module:util/event._$$EventTarget._$getInstanceWithReset\n     * @see    module:util/event._$$EventTarget._$getInstance\n     * @see    module:util/event._$$EventTarget._$allocate\n     * @param  {Object}  arg0 - 配置参数，根据控件实际情况提供配置参数支持\n     * @param  {Boolean} arg1 - 是否需要先清理已有实例\n     * @return {module:util/event._$$EventTarget} 控件实例\n     */\n    _p._$$EventTarget._$getInstanceWithReset = function(_options,_clear){\n        // clear instance\n        if (!!_clear&&!!this.__inctanse){\n            this.__inctanse._$recycle();\n            delete this.__inctanse;\n        }\n        // allocate instance\n        if (!this.__inctanse){\n            this.__inctanse = this._$allocate(_options);\n        }else{\n            this.__inctanse.__reset(_options);\n        }\n        return this.__inctanse;\n    };\n    /**\n     * 控件初始化，\n     * 子类可重写此接口业务逻辑，\n     * 子类可通过调用__super接口调用父类的初始化业务逻辑\n     * \n     * ```javascript\n     *   // 子类控件初始化业务逻辑\n     *   _pro.__init = function(){\n     *       // 调用父类控件初始化\n     *       this.__super();\n     *       // TODO something\n     *   };\n     * ```\n     * \n     * @protected\n     * @method module:util/event._$$EventTarget#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__events = {};\n        this.__events_dom = {};\n        this.id = _u._$uniqueID();\n    };\n    /**\n     * 控件重置，此接口用来接收控件配置参数的处理，\n     * 控件基类已处理以下业务逻辑：\n     * \n     * * 缓存通过配置参数输入的回调事件\n     * \n     * 子类重写此接口业务逻辑来处理具体控件对配置参数的处理，\n     * 子类通过调用__super接口调用父类的重置业务逻辑\n     * \n     * ```javascript\n     *   // 子类控件重置业务逻辑\n     *   _pro.__reset = function(_options){\n     *       // 调用父类控件重置逻辑\n     *       this.__super(_options);\n     *       // TODO something\n     *   };\n     * ```\n     * \n     * @protected\n     * @method module:util/event._$$EventTarget#__reset\n     * @param  {Object} arg0 - 配置参数，根据控件实际情况提供配置参数支持\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this._$batEvent(_options);\n    };\n    /**\n     * 控件销毁，当控件在回收时会调用此接口，基类已处理以下业务逻辑：\n     * \n     * * 通过配置参数输入的事件回调的清理\n     * * 通过__doInitDomEvent接口添加的DOM事件的清理\n     * \n     * 一般情况下控件还需回收通过重置接口__reset产生的数据，\n     * 子类可重写此接口业务逻辑来触发onbeforerecycle和onafterrecycle事件，\n     * 子类可通过调用__super接口调用父类的销毁业务逻辑\n     * \n     * ```javascript\n     *   // 子类重写控件销毁逻辑\n     *   _pro.__destroy = function(){\n     *       // 触发回收之前事件\n     *       this._$dispatchEvent('onbeforerecycle');\n     *       // 调用父类清理逻辑，如果有触发回收之后事件则以下业务逻辑需在触发回收之后事件后面调用\n     *       //this.__super();\n     *       // 清理本控件的数据\n     *       delete this.__conf0;\n     *       this.__widget2 = this.__widget2._$recycle();\n     *       // 触发回收之后事件，确保在onafterrecycle事件被清理前触发\n     *       this._$dispatchEvent('onafterrecycle');\n     *       this.__super();\n     *   };\n     * ```\n     * \n     * @protected\n     * @method module:util/event._$$EventTarget#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this._$clearEvent();\n        this.__doClearDomEvent();\n    };\n    /**\n     * 初始化事件，\n     * 重置接口__reset中需要通过_$addEvent接口添加的事件，\n     * 使用此接口添加可以在回收时自动被清理\n     * \n     * ```javascript\n     *   // 子类重置接口添加节点事件\n     *   _pro.__reset = function(_options){\n     *       this.__super(_options);\n     *       // 添加DOM事件或者自定义事件\n     *       this.__doInitDomEvent([\n     *           [document,'click',this.__onDocClick._$bind(this)],\n     *           [window,'ok',this.__onWindowOK._$bind(this)]\n     *       ]);\n     *   };\n     * ```\n     * \n     * @protected\n     * @method module:util/event._$$EventTarget#__doInitDomEvent\n     * @see    module:util/event._$$EventTarget#__doClearDomEvent\n     * @param  {Array} arg0 - 待添加的事件配置列表 \n     * @return {Void}\n     */\n    _pro.__doInitDomEvent = (function(){\n        var _doAttach = function(_args){\n            if (!_args||_args.length<3) return;\n            this.__events_dom['de-'+_u._$uniqueID()] = _args;\n            _v._$addEvent.apply(_v,_args);\n        };\n        return function(_list){\n            _u._$forEach(_list,_doAttach,this);\n        };\n    })();\n    /**\n     * 清除DOM事件，_$recycle接口会自动调用来清理这种DOM事件\n     * \n     * ```javascript\n     *   // 子类重置接口清理节点事件\n     *   _pro.__destroy = function(_options){\n     *       this.__doClearDomEvent();\n     *       this.__super(_options);\n     *   };\n     * ```\n     * \n     * @protected\n     * @method module:util/event._$$EventTarget#__doClearDomEvent\n     * @see    module:util/event._$$EventTarget#__doInitDomEvent\n     * @return {Void}\n     */\n    _pro.__doClearDomEvent = (function(){\n        var _doRemoveEvent = function(_args,_key,_map){\n            delete _map[_key];\n            _v._$delEvent.apply(_v,_args);\n        };\n        return function(){\n            _u._$loop(this.__events_dom,_doRemoveEvent);\n        };\n    })();\n    /**\n     * 清理所有组合的控件\n     * \n     * ```javascript\n     *   // 子类重置接口清理组件\n     *   _pro.__destroy = function(_options){\n     *       this.__doClearComponent(function(_inst){\n     *           // 不回收_p._$$Widget2控件实例\n     *           return _inst instanceof _p._$$Widget2;\n     *       });\n     *       this.__super(_options);\n     *   };\n     * ```\n     * \n     * @protected\n     * @method module:util/event._$$EventTarget#__doClearComponent\n     * @param  {Function} arg0 - 过滤接口，返回true表示不清理该控件\n     * @return {Void}\n     */\n    _pro.__doClearComponent = function(_filter){\n        _filter = _filter||_f;\n        _u._$loop(this,function(_inst,_key,_map){\n            if (!!_inst&&!!_inst._$recycle&&!_filter(_inst)){\n                delete _map[_key];\n                _inst._$recycle();\n            }\n        });\n    };\n    /**\n     * 回收控件，通过实例的构造类来回收当前实例\n     * \n     * ```javascript\n     *   // 通过实例的接口回收当前实例\n     *   _widget._$recycle();\n     * ```\n     * \n     * @method module:util/event._$$EventTarget#_$recycle\n     * @see    module:util/event._$$EventTarget#_$allocate\n     * @return {Void}\n     */\n    _pro._$recycle = function(){\n        this.constructor._$recycle(this);\n    };\n    /**\n     * 判断是否有注册事件回调\n     * \n     * ```javascript\n     *   // 分配实例\n     *   var _widget = _p._$$Widget._$allocate({\n     *       onok:function(){\n     *           // TODO\n     *       }\n     *   });\n     *   // 判断控件实例是否注册有onok事件回调\n     *   _widget._$hasEvent('onok');\n     * ```\n     * \n     * @method module:util/event._$$EventTarget#_$hasEvent\n     * @param  {String} arg0 - 事件类型\n     * @return {Boolean}       是否注册了事件回调\n     */\n    _pro._$hasEvent = function(_type){\n        var _type = (_type||'').toLowerCase(),\n            _event = this.__events[_type];\n        return !!_event&&_event!==_f;\n    };\n    /**\n     * 删除单个事件回调\n     * \n     * ```javascript\n     *   var _handler = function(){\n     *       // TODO\n     *   };\n     *   // 分配实例\n     *   var _widget = _p._$$Widget._$allocate({\n     *       onok:_handler\n     *   });\n     *   // 删除onok事件回调\n     *   _widget._$delEvent('onok',_handler);\n     * ```\n     * \n     * @method module:util/event._$$EventTarget#_$delEvent\n     * @param  {String}   arg0 - 事件类型\n     * @param  {Function} arg1 - 事件处理函数\n     * @return {Void}\n     */\n    _pro._$delEvent = function(_type,_event){\n        var _type = (_type||'').toLowerCase(),\n            _events = this.__events[_type];\n        if (!_u._$isArray(_events)){\n            if (_events==_event){\n                delete this.__events[_type];\n            }\n            return;\n        }\n        // batch remove\n        _u._$reverseEach(\n            _events,function(_func,_index,_list){\n                if (_func==_event){\n                    _list.splice(_index,1);\n                }\n            }\n        );\n        if (!_events.length){\n            delete this.__events[_type];\n        }\n    };\n    /**\n     * 重置事件，覆盖原有事件\n     * \n     * ```javascript\n     *   // 分配实例\n     *   var _widget = _p._$$Widget._$allocate();\n     *   // 设置控件事件回调\n     *   _widget._$setEvent('onok',function(){\n     *       // TODO something\n     *   });\n     *   _widget._$setEvent('oncancel',function(){\n     *       // TODO something\n     *   });\n     * ```\n     * \n     * @method module:util/event._$$EventTarget#_$setEvent\n     * @param  {String}   arg0 - 事件类型，大小写不敏感\n     * @param  {Function} arg1 - 事件处理函数\n     * @return {Void}\n     */\n    _pro._$setEvent = function(_type,_event){\n        if (!!_type&&_u._$isFunction(_event)){\n            this.__events[_type.toLowerCase()] = _event;\n        }\n    };\n    /**\n     * 批量添加事件\n     * \n     * ```javascript\n     *   // 分配实例\n     *   var _widget = _p._$$Widget._$allocate();\n     *   // 批量设置控件事件回调\n     *   _widget._$batEvent({\n     *       onok:function(){\n     *           // TODO something\n     *       },\n     *       oncancel:function(){\n     *           // TODO something\n     *       }\n     *   });\n     * ```\n     * \n     * @method module:util/event._$$EventTarget#_$batEvent\n     * @see    module:util/event._$$EventTarget#_$setEvent\n     * @param  {Object} arg0 - 事件集合,{type:function}\n     * @return {Void}\n     */\n    _pro._$batEvent = (function(){\n        var _doSetEvent = function(_event,_type){\n            this._$setEvent(_type,_event);\n        };\n        return function(_events){\n            _u._$loop(_events,_doSetEvent,this);\n        };\n    })();\n    /**\n     * 清除事件，没有指定类型则清除所有事件\n     * \n     * ```javascript\n     *   // 分配实例\n     *   var _widget = _p._$$Widget._$allocate({\n     *       onok:function(){\n     *           // TODO something\n     *       }\n     *   });\n     *   // 清除onok事件回调\n     *   _widget._$clearEvent('onok');\n     *   // 清除所有时间回调\n     *   _widget._$clearEvent();\n     * ```\n     * \n     * @method module:util/event._$$EventTarget#_$clearEvent\n     * @param  {String} arg0 - 事件类型\n     * @return {Void}\n     */\n    _pro._$clearEvent = (function(){\n        var _doClearEvent = function(_event,_type){\n            this._$clearEvent(_type);\n        };\n        return function(_type){\n            var _type = (_type||'').toLowerCase();\n            if (!!_type){\n                delete this.__events[_type];\n            }else{\n                _u._$loop(this.__events,_doClearEvent,this);\n            }\n        };\n    })();\n    /**\n     * 追加事件，通过此接口可以对同一个事件添加多个回调函数\n     * \n     * ```javascript\n     *   // 分配实例\n     *   var _widget = _p._$$Widget._$allocate({\n     *       onok:function(){\n     *           // TODO something\n     *       }\n     *   });\n     *   // 追加事件回调\n     *   _widget._$addEvent({\n     *       onok:function(){\n     *           // TODO something\n     *       }\n     *   });\n     * ```\n     * \n     * @method module:util/event._$$EventTarget#_$addEvent\n     * @param  {String}   arg0 - 事件类型\n     * @param  {Function} arg1 - 事件处理函数\n     * @return {Void}\n     */\n    _pro._$addEvent = function(_type,_event){\n        // check type and event\n        if (!_type||!_u._$isFunction(_event)){\n            return;\n        }\n        // cache event\n        _type = _type.toLowerCase();\n        var _events = this.__events[_type];\n        if (!_events){\n            this.__events[_type] = _event;\n            return;\n        }\n        if (!_u._$isArray(_events)){\n            this.__events[_type] = [_events];\n        }\n        this.__events[_type].push(_event);\n    };\n    /**\n     * 调用事件，一般在控件实现的具体业务逻辑中使用\n     * \n     * ```javascript\n     *   // 分配实例\n     *   var _widget = _p._$$Widget._$allocate({\n     *       onok:function(){\n     *           // TODO something\n     *       }\n     *   });\n     *   // 触发控件onok事件\n     *   _widget._$dispatchEvent('onok');\n     *   \n     *   // 在控件实现的业务逻辑中使用\n     *   _pro.__doSomething = function(){\n     *       // TODO something\n     *       // 触发onok事件\n     *       this._$dispatchEvent('onok');\n     *   };\n     * ```\n     * \n     * @method module:util/event._$$EventTarget#_$dispatchEvent\n     * @param  {String}   arg0 - 事件类型，不区分大小写\n     * @param  {Variable} arg1 - 事件可接受参数，具体看调用时的业务逻辑\n     * @return {Void}\n     */\n    _pro._$dispatchEvent = function(_type){\n        var _type = (_type||'').toLowerCase(),\n            _event = this.__events[_type];\n        if (!_event) return;\n        var _args = _r.slice.call(arguments,1);\n        // single event\n        if (!_u._$isArray(_event)){\n            _event.apply(this,_args);\n            return;\n        }\n        // event list\n        _u._$forEach(\n            _event,function(_handler){\n                if (DEBUG){\n                    _handler.apply(this,_args);\n                }else{\n                    try{\n                        _handler.apply(this,_args);\n                    }catch(ex){\n                        // ignore\n                        console.error(ex.message);\n                        console.error(ex.stack);\n                    }\n                }\n            },this\n        );\n    };\n    \n    if (CMPT){\n        _p._$$Event = _p._$$EventTarget;\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/file/demo/file.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test file</title>\n  </head>\n  <body>\n    <input type=\"file\" id=\"abc\" multiple=\"true\"/>\n    <script>\n        alert('multiple' in document.createElement('input'));\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/file/demo/paste.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <title>NEJ实例 - 黏贴</title>\n    <meta charset=\"utf-8\" />\n    <script>\n        function log(m){\n            var p = document.createElement('p');\n            p.innerHTML = m;\n            document.body.appendChild(p);\n        }\n    </script>\n</head>\n<body>\n<p><input type=\"text\" id=\"abc\"/></p>\n<p><textarea id=\"def\"></textarea></p>\n<p><input type=\"button\" value=\"bind\" id=\"ggg\"/>\n    <input type=\"button\" value=\"unbind\" id=\"ghi\"/></p>\n<script src=\"../../../define.js\"></script>\n<script>\n    NEJ.define([\n        'base/event',\n        'base/element',\n        '../paste.js'\n    ],function(v,e,t){\n        v._$addEvent('ggg','click',function(){\n            t._$bind('abc',{\n                accept:'image',\n                dataurl:true,\n                onpaste:function(event){\n                    log(event.type+':'+event.dataurl);\n                    log(event.url);\n                }\n            });\n            t._$bind('def',{\n                accept:'text',\n                onpaste:function(event){\n                    log(event.type+':'+event.content);\n                }\n            });\n        });\n        v._$addEvent('ghi','click',function(){\n            t._$unbind('abc');\n            t._$unbind('def');\n        });\n    });\n</script>\n</body>\n</html>"
  },
  {
    "path": "src/util/file/demo/select.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test file upload</title>\n    <meta charset=\"utf-8\"/>\n  </head>\n  <body>\n    <label id=\"abc\">select file</label>\n    <script src=\"../../../define.js\"></script>\n    <script>\n      NEJ.define([\n          '../select.js',\n          'util/ajax/xdr'\n      ],function(_x,_j){\n          \n          _x._$bind('abc',{\n              name:'img',\n              multiple:true,\n              onchange:function(_event){\n                  _event.form.action = './upload';\n                  _j._$upload(_event.form,{\n                      onload:function(){\n\n                      }\n                  });\n              }\n          });\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/file/demo/upload",
    "content": "{\"result\":true}"
  },
  {
    "path": "src/util/file/paste.js",
    "content": "/*\n * ------------------------------------------\n * 黏贴接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/file/paste */\nNEJ.define([\n    'base/util',\n    'base/event',\n    'base/element',\n    '{platform}paste.js'\n],function(u,v,e,h,p,o,f){\n    // node cache\n    var cache = [];\n    /**\n     * 绑定黏贴操作\n     *\n     * 结构举例\n     * ```html\n     * <input type=\"text\" id=\"message\"/>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/file/paste'\n     * ],function(p){\n     *     // 绑定黏贴行为\n     *     p._$bind('message',{\n     *         accept:'image',\n     *         dataurl:true,\n     *         onpaste:function(event){\n     *             // event.type    - 内容类型，string或者file\n     *             // event.content - 内容信息\n     *             // event.dataurl - 如果是图片，此属性表示图片地址\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method module:util/file/paste._$bind\n     * @see    module:util/file/paste._$unbind\n     * @param  {String|Node} node        - 节点ID或者节点对象\n     * @param  {Object}   config         - 配置信息\n     * @param  {String}   config.accept  - 支持黏贴的格式，如image表示图片、text表示纯文本，或者text/plain表示精确的纯文本\n     * @param  {Boolean}  config.dataurl - 如果accept为image，则标识是否导出dataurl，拿到的dataurl可以直接用于img标签的src属性预览本地图片\n     * @param  {Function} config.onpaste - 黏贴回调，输入内容为 {type:'string|file',content:xxxx,dataurl:'xxxx'}\n     * @return {Void}\n     */\n    p._$bind = function(node,options){\n        // check node\n        node = e._$get(node);\n        if (!node){\n            return;\n        }\n        // check binded\n        var id = e._$id(node);\n        if (!!cache[id]){\n            return;\n        }\n        // past event handler\n        var ret = u._$merge(\n            {onpaste:f},options\n        );\n        ret.handler = h.\n            __doDumpContent._$bind(null,ret);\n        v._$addEvent(node,'paste',ret.handler);\n        cache[id] = ret;\n    };\n    /**\n     * 解绑黏贴行为\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/file/paste'\n     * ],function(p){\n     *     // 解绑黏贴行为\n     *     p._$unbind('message');\n     * });\n     * ```\n     *\n     * @method module:util/file/paste._$unbind\n     * @see    module:util/file/paste._$bind\n     * @param  {String|Node} node - 节点ID或者节点对象\n     * @return {Void}\n     */\n    p._$unbind = function(node){\n        // check node\n        node = e._$get(node);\n        if (!node){\n            return;\n        }\n        // check binded\n        var id = e._$id(node),\n            ret = cache[id];\n        if (!!ret){\n            v._$delEvent(\n                node,'paste',\n                ret.handler\n            );\n            delete cache[id];\n        }\n    };\n});"
  },
  {
    "path": "src/util/file/platform/paste.js",
    "content": "/*\n * ------------------------------------------\n * Ҫƽ̨Ľӿʵļ\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/util',\n    'base/event',\n    'base/element'\n],function(u,v,e,p){\n\n    //function dataURItoBlob(dataURI, callback) {\n    //    // convert base64 to raw binary data held in a string\n    //    // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this\n    //    var byteString = atob(dataURI.split(',')[1]);\n    //\n    //    // separate out the mime component\n    //    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]\n    //\n    //    // write the bytes of the string to an ArrayBuffer\n    //    var ab = new ArrayBuffer(byteString.length);\n    //    var ia = new Uint8Array(ab);\n    //    for (var i = 0; i < byteString.length; i++) {\n    //        ia[i] = byteString.charCodeAt(i);\n    //    }\n    //\n    //    // write the ArrayBuffer to a blob, and you're done\n    //    var bb = new BlobBuilder();\n    //    bb.append(ab);\n    //    return bb.getBlob(mimeString);\n    //}\n    /**\n     * ļϢ\n     * @param file\n     * @param ret\n     * @param callback\n     * @private\n     */\n    p.__doDumpFile = function(file,config){\n        var event = {\n            type:'file',\n            content:file,\n            url:URL.createObjectURL(file)\n        };\n        if (!!config.dataurl){\n            var reader = new FileReader();\n            reader.onload = function(ev){\n                event.dataurl = ev.target.result;\n                config.onpaste(event);\n            };\n            reader.readAsDataURL(file);\n        }else{\n            config.onpaste(event);\n        }\n    };\n    /**\n     * ͼƬϢ\n     * @private\n     */\n    p.__doDumpImage = (function(){\n        var div = e._$create('div');\n        div.contentEditable = true;\n        e._$style(div,{\n            position:'absolute',\n            top:0,\n            left:'300px',\n            width:'200px',\n            height:'200px',\n            border:'1px solid #aaa'\n        });\n        document.body.appendChild(div);\n        return function(config){\n            div.focus();\n            window.setTimeout(function(){\n                var img = div.getElementsByTagName('img')[0];\n                if (!!img){\n                    config.onpaste({\n                        type:'file',\n                        url:img.src,\n                        content:img.src,\n                        dataurl:img.src\n                    });\n                }\n            },15);\n        };\n    })();\n    /**\n     * Ϣ\n     * @param event\n     * @private\n     */\n    p.__doDumpContent = (function(){\n        var pmap = {\n            string:function(it,ret){\n                it.getAsString(function(content){\n                    ret.onpaste({\n                        type:'string',\n                        content:content||''\n                    });\n                });\n            },\n            file:function(it,ret){\n                p.__doDumpFile(it.getAsFile(),ret);\n            }\n        };\n        return function(ret,event){\n            var accept = ret.accept||'',\n                board = event.clipboardData||{};\n            u._$forEach(board.items,function(it){\n                if (!accept||it.type.indexOf(accept)==0){\n                    v._$stop(event);\n                    var func = pmap[it.kind];\n                    if (u._$isFunction(func)){\n                        func(it,ret);\n                    }\n                    return !0;\n                }\n            });\n        };\n    })();\n\n    return p;\n});"
  },
  {
    "path": "src/util/file/platform/paste.patch.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/util',\n    'base/event',\n\t'./paste.js'\n],function(u,v,h){\n    // for gecko\n    NEJ.patch('GR',function(){\n        /**\n         * 导出拷贝信息\n         * @param event\n         * @private\n         */\n        h.__doDumpContent = function(ret,event){\n            var accept = ret.accept||'',\n                board = event.clipboardData||{},\n                type = (board.types||[])[0]||'';\n            // check string type\n            if (!accept||type.indexOf(accept)==0){\n                v._$stop(event);\n                if (type.indexOf('text')==0){\n                    ret.onpaste({\n                        type:'string',\n                        content:board.getData('text')\n                    });\n                    return;\n                }\n            }\n            // check image data\n            h.__doDumpImage(ret);\n            // check file type\n            u._$forEach(board.files,function(it){\n                if (!accept||it.type.indexOf(accept)==0){\n                    v._$stop(event);\n                    h.__doDumpFile(it,ret);\n                    return !0;\n                }\n            });\n        };\n    });\n    // for trident\n    NEJ.patch('TR',function(){\n        /**\n         * 导出拷贝信息\n         * @param event\n         * @private\n         */\n        h.__doDumpContent = function(ret,event){\n            console.log(event)\n        };\n    });\n\treturn h;\n});\n"
  },
  {
    "path": "src/util/file/platform/select.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define(function(p){\n\t/**\n\t * 关联file的label点击事件\n\t * @return {Void}\n\t */\n\tp.__handleFileLabelClick = function(){\n\t\t//do nothing\n\t};\n\n\treturn p;\n});"
  },
  {
    "path": "src/util/file/platform/select.patch.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/event',\n\t'./select.js'\n],function(_v,_h,_p,_o,_f,_r){\n    // fro gecko\n\tNEJ.patch('GR',function(){\n\t\t/**\n\t\t * 关联file的label点击事件\n\t\t * @return {Void}\n\t\t */\n\t    _h.__handleFileLabelClick = (function(){\n\t    \tvar _doLabelClick = function(_event){\n\t            _v._$stop(_event);\n\t            _v._$getElement(_event,'t:label').control.click();\n\t        };\n\t    \treturn function(_label){\n\t\t    \t_v._$addEvent(\n\t\t    \t\t_label,'click',_doLabelClick\n\t\t    \t);\n\t\t    };\n\t    })();\n\t});\n\n\treturn _h;\n});\n"
  },
  {
    "path": "src/util/file/save.js",
    "content": "/*\n * ------------------------------------------\n * 文件下载接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/file/save */\nNEJ.define([\n    'base/global',\n    'base/element',\n    'base/event',\n    'base/util',\n    'base/chain'\n],function(NEJ,_e,_v,_u,_x,_p,_o,_f,_r){\n    var _cache = {};\n    /*\n     * 执行另存为\n     * @param  {Event} 节点标识\n     * @return {Void}\n     */\n    var _doSaveAs = (function(){\n        var _getFileInfo = function(_id){\n            var _conf = _cache[_id];\n            if (!_conf) return;\n            var _url = _conf.url,\n                _name = _conf.name;\n            if (_u._$isFunction(_url)){\n                _url = _url();\n            }\n            if (!_name){\n                var _arr = _url.split('/');\n                _name = _arr.pop();\n            }\n            return {\n                url:_url,\n                name:_name\n            };\n        };\n        return function(_event){\n            var _el = _v._$getElement(_event),\n                _id = _e._$id(_el),\n                _info = _getFileInfo(_id);\n            if (!!_info){\n                _el.href = _info.url;\n                if ('download' in _el){\n                    _el.download = _info.name;\n                }else{\n                    _el.target = '_blank';\n                }\n            }\n        };\n    })();\n    /**\n     * 绑定文件下载行为\n     *\n     * 结构举例\n     * ```html\n     * <a id=\"button_id\">下载文件</a>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/file/save'\n     * ],function(_e){\n     *     // 绑定文件下载行为\n     *     _e._$bind('button_id',{\n     *         name:'test.txt',\n     *         url:function(){\n     *             // 动态组装下载地址\n     *             return obj.url+'?'+new Date;\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/file/save._$bind\n     * @see      module:util/file/save._$unbind\n     * @param    {String|Node}     arg0 - 下载点击链接节点，必须是A节点\n     * @param    {Object}          arg1 - 可选配置参数\n     * @property {String|Function} url  - 下载文件地址或者地址生成函数\n     * @property {String}          name - 保存的文件名称，没有指定name则取url中文件名\n     * @return   {Void}\n     */\n    /**\n     * @method CHAINABLE._$bind\n     * @see module:util/file/save._$bind\n     */\n    _p._$bind = function(_button,_options){\n        var _id = _e._$id(_button);\n        if (!!_cache[_id]) return;\n        var _node = _e._$get(_button);\n        if (_node.tagName!='A') return;\n        _cache[_id] = _u._$merge({},_options);\n        _v._$addEvent(_id,'click',_doSaveAs);\n    };\n    /**\n     * 解绑文件下载行为\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/file/save'\n     * ],function(_e){\n     *     // 解绑文件下载行为\n     *     _e._$unbind('button_id');\n     * });\n     * ```\n     *\n     * @method module:util/file/save._$unbind\n     * @see    module:util/file/save._$bind\n     * @param  {String|Node} arg0 - 下载点击按钮节点\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$unbind\n     * @see module:util/file/save._$unbind\n     */\n    _p._$unbind = function(_button){\n        var _id = _e._$id(_button);\n        if (!_cache[_id]) return;\n        delete _cache[_id];\n        _v._$delEvent(_id,'click',_doSaveAs);\n    };\n    // for chainable method\n    _x._$merge(_p);\n\n    if (CMPT){\n        var _x = NEJ.P('nej.e');\n        _x._$bindSaveAsAction = _p._$bind;\n        _x._$unbindSaveAsAction = _p._$unbind;\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/file/select.js",
    "content": "/*\n * ------------------------------------------\n * 文件选择接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/file/select */\nNEJ.define([\n    'base/global',\n    'base/element',\n    'base/event',\n    'base/util',\n    '{platform}select.js',\n    'base/chain'\n],function(NEJ,_e,_v,_u,_h,_x,_p,_o,_f,_r){\n    var _cache = {},// {id:{lab:'label',pid:'parent'}}\n        _class = _e._$pushCSSText('.#<uispace>{position:absolute;width:0;height:0;overflow:hidden;}');\n    /**\n     * 文件选择按钮封装\n     *\n     * 结构举例\n     * ```html\n     * <p>\n     *   <!-- 必须为LABEL标签 -->\n     *   <label id=\"abc\">选择文件</label>\n     * </p>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/file/select'\n     * ],function(_e){\n     *     // 绑定文件选择按钮\n     *     var _id = _e._$bind('abc',{\n     *         multiple:true,\n     *         onchange:function(_event){\n     *             // _event.form\n     *             // _event.id\n     *             // 如果要删除某个文件选择节点必须使用以下接口\n     *             _e._$remove(_event.id);\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/file/select._$bind\n     * @param    {String|Node} arg0     - 绑定选择文件的节点，必须为label节点，且未设置for属性\n     * @param    {Object}      arg1     - 配置参数\n     * @property {String|Node} form     - 文件选择控件所在的表单，默认全新生成一个\n     * @property {String|Node} parent   - 如果新生成form表单则可以指定表单容器节点，默认为document.body\n     * @property {String}      name     - 单个文件选择支持指定提交时文件名称\n     * @property {String}      clazz    - 表单样式名称，可用于控制表单位置\n     * @property {Boolean}     multiple - 是否允许多选，默认单选\n     * @property {String}      accept   - 文件类型过滤，如image/*或者.png，多个类型用逗号分隔\n     * @property {Object}      param    - 参数集合，以input.hidden的形式放置在form中提交\n     * @property {Function}    onchange - 文件选择变化触发回调，{form:form,id:'xxx'}，\n     *                                    form - 文件选择控件封装表单对象，\n     *                                    id   - 当前变化的文件选择控件的ID\n     */\n    /**\n     * @method CHAINABLE._$bind\n     * @see module:util/file/select._$bind\n     */\n    _p._$bind = (function(){\n        // init cache\n        var _doInitCache = function(_id){\n            var _cch = _cache[_id];\n            if (!_cch){\n                _cch = {};\n                _cache[_id] = _cch;\n            }\n            return _cch;\n        };\n        // init param\n        var _doInitParam = function(_form,_param){\n            if (!_param) return;\n            var _arr = [];\n            _u._$loop(_param,function(_value,_key){\n                _arr.push('<input type=\"hidden\" name=\"'+_key+'\" value=\"'+_value+'\">');\n            });\n            _form.insertAdjacentHTML('afterBegin',_arr.join(''));\n        };\n        // build parent\n        var _doBuildParent = function(_id,_form,_clazz,_param,_fbox){\n            var _parent,\n                _cch = _cache[_id],\n                _cls = _class+' '+(_clazz||'');\n            _form = _e._$get(_form);\n            if (!!_form){\n                _parent = _e._$create('div',_cls);\n                _form.appendChild(_parent);\n                _e._$dataset(_form,'id',_id);\n                _doInitParam(_form,_param);\n            }else{\n                _parent = _e._$create('form',_cls);\n                _e._$dataset(_parent,'id',_id);\n                _doInitParam(_parent,_param);\n                (_fbox||document.body).appendChild(_parent);\n            }\n            _cch.pid = _e._$id(_parent);\n        };\n        var _doAppendFile = function(_id,_cch){\n            var _accept = _cch.accept||'';\n            if (!!_accept){\n                _accept = 'accept=\"'+_accept+'\"';\n            }\n            var _multiple = '';\n            if (!!_cch.multiple){\n                _multiple = 'multiple=\"true\"';\n            }\n            var _cch = _cache[_id],\n                _fid = _id+\"-\"+_cch.nmb,\n                _file = _e._$html2node('<input type=\"file\" '+_multiple+' '+_accept+' contenteditable=\"false\" id=\"'+_fid+'\"/>');\n            _cch.nmb++;\n            _e._$get(_cch.pid).appendChild(_file);\n            _v._$addEvent(_file,'change',_onFileChange);\n            return _fid;\n        };\n        // file select\n        var _onFileChange = function(_event){\n            var _element = _v._$getElement(_event),\n                _id = _element.id,\n                _arr = _id.split('-'),\n                _cch = _cache[_arr[0]];\n            if (!_element.value) return;\n            if (_cch.multiple){\n                _e._$get(_cch.lab).htmlFor =\n                    _doAppendFile(_arr[0],_cch);\n            }\n            if (!_element.name){\n                var _sufix = '';//!_cch.multiple?'':('-'+(_cch.nmb-2));\n                _element.name = _cch.name+_sufix;\n            }\n            _cch.onchange({\n                id:_id,\n                form:_element.form,\n                target:_e._$get(_cch.lab)\n            });\n        };\n        return function(_element,_options){\n            _element = _e._$get(_element);\n            if (!_element||\n                 _element.tagName!='LABEL') return;\n            _e._$dumpCSSText();\n            var _id = _u._$uniqueID(),\n                _cch = _doInitCache(_id);\n            _options = _options||_o;\n            _doBuildParent(\n                _id,\n                _options.form,\n                _options.clazz,\n                _options.param,\n                _e._$get(_options.parent)\n            );\n            _cch.nmb = 0;\n            _cch.name = _options.name||'file';\n            _cch.lab = _e._$id(_element);\n            _cch.accept = _options.accept||'';\n            _cch.multiple = !!_options.multiple;\n            _cch.onchange = _options.onchange||_f;\n            _element.htmlFor =\n                _doAppendFile(_id,_cch);\n            _h.__handleFileLabelClick(_element);\n            return _id;\n        };\n    })();\n    /**\n     * 根据ID取选中文件的form表单\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/file/select'\n     * ],function(_e){\n     *     // 取文件绑定的表单节点\n     *     var _form = _e._$get(_id);\n     * });\n     * ```\n     *\n     * @method module:util/file/select._$get\n     * @see    module:util/file/select._$file\n     * @param  {String} arg0 - 标识\n     * @return {Node}          表单节点\n     */\n    _p._$get = function(_id){\n        var _conf = _cache[_id];\n        if (!_conf) return;\n        var _form = _e._$get(_conf.pid);\n        if (!_form) return;\n        if (_form.tagName!='FORM'){\n            _form = _form.parentNode;\n        }\n        return _form;\n    };\n    /**\n     * 根据ID删除选中文件的form表单\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/file/select'\n     * ],function(_e){\n     *     // 解绑文件选择按钮\n     *     _e._$unbind(_id);\n     * });\n     * ```\n     *\n     * @method module:util/file/select._$unbind\n     * @see    module:util/file/select._$file\n     * @param  {String} arg0 - 标识\n     * @return {Object}        表单信息\n     */\n    _p._$unbind = function(_id){\n        var _conf = _cache[_id];\n        if (!!_conf){\n            var _form = _p._$get(_id);\n            //_e._$remove(_conf.pid);\n            delete _cache[_id];\n            return {\n                form:_form,\n                parent:_conf.pid\n            };\n        }\n    };\n    /**\n     * 判断系统是否支持文件选择功能\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/file/select'\n     * ],function(file){\n     *     // 判断是否支持文件选择功能\n     *     if (file._$selectable()){\n     *         // TODO something\n     *     }\n     * });\n     * ```\n     *\n     * @method module:util/file/select._$selectable\n     * @return {Boolean} 是否支持文件选择功能\n     */\n    _p._$selectable = (function(){\n        var _enable;\n        return function(){\n            if (_enable==null){\n                var _input = document.createElement('input');\n                _input.type = 'file';\n                _enable = !_input.disabled;\n            }\n            return _enable;\n        };\n    })();\n\n    // for chainable method\n    _x._$merge({_$bind:_p._$bind});\n\n    if (CMPT){\n        var _x = NEJ.P('nej.e');\n        _x._$file = _p._$bind;\n        _x._$getFileForm = _p._$get;\n        _x._$removeFileForm = _p._$unbind;\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/file/test/save.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>save测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit save test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <a id=\"save-box\">save</a>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./save.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/file/test/save.test.js",
    "content": "NEJ.define(['util/file/save'],function(){\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v');\n    test('save',function(){\n        expect(1);\n        stop();\n        _e._$bindSaveAsAction('save-box',{\n            name:'xxx',\n            url:function(){\n                ok('save ok');\n                start();\n                return 'xxx'\n            }\n        });\n    });\n});"
  },
  {
    "path": "src/util/file/test/select.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>select测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n  \t\t<style type=\"text/css\">\n  \t\t\tlabel{width:50px;height:50px;}\n  \t\t</style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit select test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n \t\t<div><label id=\"select-box\">选择文件</label></div>\n \t\t<div><label id=\"select-box2\">多选文件</label></div>\n \t\t<script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./select.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/util/file/test/select.test.js",
    "content": "var f = function(){\n\tmodule(\"selectTest\");\n    \n\tvar _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v'),\n        _i = _('nej.ui.cmd');\n\n\ttest('selectTest',function(){\n\t\tstop();\n\t\t _e._$file('select-box',{\n\t\t \tmultiple:false,\n\t\t \tonchange:function(_event){\n\t\t \t\tok(true,'文件ID为'+_event.id);\n\t\t \t\tok(true,'表单ID为'+_event.form.id);\n\t\t \t\tstart();\n\t\t\t}\n\t\t});\n\t});\n\n\ttest('selectTest multiple',function(){\n\t\tstop();\n\t\t _e._$file('select-box2',{\n\t\t \tmultiple:true,\n\t\t \tonchange:function(_event){\n\t\t \t\tok(true,'文件ID为'+_event.id);\n\t\t \t\tok(true,'表单ID为'+_event.form.id);\n\t\t \t\tstart();\n\t\t\t}\n\t\t});\n\t});\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}select.test.js',['{lib}util/file/select.js'],f);\n});\n\n  "
  },
  {
    "path": "src/util/flash/flash.html",
    "content": "{var hide  = defined(\"hidden\")&&!!hidden}\n{var param = defined(\"params\")&&params||NEJ.O}\n{var width = !hide?width:\"1px\",height = !hide?height:\"1px\"}\n{if hide}<div style=\"position:absolute;top:0;left:0;width:1px;height:1px;z-index:10000;overflow:hidden;\">{/if}\n<object classid = \"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\"\n        codebase = \"http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab\"\n        width = \"${width|default:\"100px\"}\"\n        height = \"${height|default:\"100px\"}\" id=\"${id}\">\n    <param value=\"${src}\" name=\"movie\">\n    {for x in param}\n    <param value=\"${x}\" name=\"${x_key}\"/>\n    {/for}\n    <embed src=\"${src}\" name=\"${id}\"\n           width=\"${width|default:\"100px\"}\"\n           height=\"${height|default:\"100px\"}\"\n           pluginspage=\"http://www.adobe.com/go/getflashplayer\"\n           type=\"application/x-shockwave-flash\"\n           {for x in param}${x_key}=\"${x}\" {/for}></embed>\n</object>\n{if hide}</div>{/if}"
  },
  {
    "path": "src/util/flash/flash.js",
    "content": "/*\n * ------------------------------------------\n * Flash对象支持实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/flash/flash */\nNEJ.define([\n    'base/global',\n    'base/element',\n    'base/event',\n    'base/util',\n    'util/template/jst',\n    'util/timer/animation',\n    '{platform}flash.js',\n    'text!./flash.html'\n],function(NEJ,_e,_v,_u,_t0,_t1,_h,_html,_p,_o,_f,_r){\n    var _seed_html = _t0._$add(_html);\n    /**\n     * 页面嵌入flash，NEJ嵌入Flash如果需要同JS交互的遵循以下规则\n     *\n     *  1. Flash对象提供JS可访问接口 inited （返回Boolean值）\n     *  2. 如果Flash未初始化完成inited返回为false\n     *  3. 如果Flash初始化完成inited返回为true\n     *  4. inited返回true表示Flash已完成所有初始化，此时JS可调用Flash的API\n     *\n     * Flash事件规则\n     *\n     *  1. JS中使用window.onflashevent监听flash中的事件（此步骤NEJ已封装）\n     *  2. Flash通过flashvars参数输入当前flash的ID，如 &lt;param name=\"flashvars\" value=\"id=ab&a=b\"/&gt;\n     *  3. Flash在需要触发事件时调用window.onflashevent回调函数，并输入一个Object作为参数,Object信息包括\n     *     type   [String] - 鼠标事件类型，如click/mouseover/mouseout/play/pause...\n     *     target [String] - 触发事件的flash标识，通过flashvars参数输入的id参数，做了encodeURIComponent，如a%23b\n     *     ...\n     *\n     * 结构举例\n     * ```html\n     * <div id='flash'></div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/flash/flash'\n     * ],function(_e){\n     *     // 生成flash对象，可以设置宽高，地址，父节点，flash参数在params中设置\n     *     // flash需要提供inited接口，返回falsh已经准备好的状态\n     *     _e._$flash({\n     *         src:'../../qunit/res/FlexChart.swf',\n     *         hidden:false,\n     *         parent:'flash',\n     *         width:900,\n     *         height:600,\n     *         params:{\n     *             flashvars:'',\n     *             wmode:'transparent',\n     *             allowscriptaccess:'always'\n     *         },\n     *         onready:function(_flash){\n     *             // 返回准备好的flash对象\n     *             // 如果没有传入flash对象则表示无法识别到flash\n     *         },\n     *         oncustom:function(_event){\n     *             // 自定义事件需Flash同JS预先协定好自定义事件名称，如这里的oncustom\n     *             // Flash中通过调用JS的window.onflashevent({id:2222,type:'custom',...})调入此回调\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method   module:util/flash/flash._$flash\n     * @param    {Object}      arg0    - 可选配置参数\n     * @property {String}      src     - Flash文件地址，必须指定地址\n     * @property {Boolean}     hidden  - Flash是否不可见\n     * @property {Number}      width   - Flash显示宽度，设为不可见时可以不设此参数\n     * @property {Number}      height  - Flash显示高度，设为不可见时可以不设此参数\n     * @property {String|Node} parent  - 容器节点，默认为document.body\n     * @property {Object}      params  - 设置参数，object标签中的param标签参数\n     * @property {String|Node} target  - 触发事件的源节点\n     * @property {Function}    onready - Flash初始化完毕触发事件，输入可交互的Flash对象\n     * @return   {Void}\n     */\n    _p._$flash = (function(){\n        var _cache = {},_title,\n            _reg0 = /^(?:mouse.*|(?:dbl)?click)$/i;\n        // flash event\n        window.onflashevent = function(_event){\n            var _id = decodeURIComponent(_event.target),\n                _type = _event.type.toLowerCase();\n            // check mouse event bubble\n            var _target = _cache[_id+'-tgt'];\n            if (!!_target&&_reg0.test(_type)){\n                _doMouseEventBubble(\n                    _target,_event\n                );\n            }\n            // check id-type handler\n            var _handler = _cache[_id+'-on'+_type];\n            if (!!_handler){\n                var _result = '';\n                try{\n                    _result = _handler(_event);\n                }catch(e){\n                    // ignore\n                }\n                return _result;\n            }\n        };\n        // append flash element\n        var _doInitDOM = function(_options){\n            // bugfix for ie title with flash\n            _title = document.title;\n            var _parent = _e._$get(_options.parent)||document.body,\n                _html = _t0._$get(_seed_html,_options);\n            _parent.insertAdjacentHTML(\n               !_options.hidden?'beforeEnd':'afterBegin',_html\n            );\n        };\n        // listen flash mouse event\n        var _doMouseEventBubble = function(_id,_event){\n            var _type = _event.type.toLowerCase();\n            _t1.requestAnimationFrame(function(){\n                _v._$dispatchEvent(_id,_type);\n            });\n        };\n        // check flash init state\n        var _doCheckFlashInit = function(_flash){\n            return !!_flash&&!!_flash.inited&&!!_flash.inited();\n        };\n        var _doCheckFlash = function(_id){\n            var _arr = [document.embeds[_id],\n                       _e._$get(_id),document[_id],window[_id]],\n                _index = _u._$forIn(_arr,_doCheckFlashInit),\n                _flash = _arr[_index],\n                _ctkey = _id+'-count';\n            _cache[_ctkey]++;\n            // remove count check for chrome bug\n            if (!!_flash){ // ||_cache[_ctkey]>100\n                if (!!_title){\n                    document.title = _title;\n                    _title = null;\n                }\n                _cache[_id](_flash);\n                delete _cache[_id];\n                delete _cache[_ctkey];\n                return;\n            }\n            window.setTimeout(_doCheckFlash._$bind(null,_id),300);\n        };\n        // init flash event\n        var _doInitFlashEvent = function(_options){\n            // init flash vars\n            var _id = _options.id,\n                _params = _options.params;\n            if (!_params){\n                _params = {};\n                _options.params = _params;\n            }\n            var _vars = _params.flashvars||'';\n            _vars += (!_vars?'':'&')+('id='+_id);\n            // delegate mouse event bubble\n            if (!_options.hidden&&(!!_options.target||\n                 _h.__canFlashEventBubble(_params.wmode))){\n                var _tid = _e._$id(_options.target)||\n                           _e._$id(_options.parent);\n                _cache[_id+'-tgt'] = _tid;\n            }\n            _params.flashvars = _vars;\n            // check event callback\n            _u._$loop(_options,function(_value,_key){\n                if (_u._$isFunction(_value)&&_key!='onready'){\n                    _cache[_id+'-'+_key] = _value;\n                }\n            });\n        };\n        return function(_options){\n            _options = NEJ.X({},_options);\n            if (!_options.src) return;\n            var _id = '_'+_u._$uniqueID();\n            _options.id = _id;\n            // delegate event\n            _doInitFlashEvent(_options);\n            // append flash\n            _doInitDOM(_options);\n            // check flash ready\n            if (!_options.onready) return;\n            _cache[_id] = _options.onready;\n            _cache[_id+'-count'] = 0;\n            _doCheckFlash(_id);\n        };\n    })();\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.e'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/flash/platform/flash.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/platform'\n],function(_m,_p,_o,_f,_r){\n    /**\n     * 判断是否需要对Flash事件做代理，\n     * 主要fix flash上的鼠标事件没法响应到DOM节点上的问题\n     * @return {Boolean} 是否做代理\n     */\n    _p.__canFlashEventBubble = function(_wmode){\n        return (_wmode||'').toLowerCase()!='transparent';\n    };\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/flash/platform/flash.patch.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    './flash.js',\n    'base/platform'\n],function(_h,_m,_p,_o,_f,_r){\n    // for ie\n    NEJ.patch('TR',function(){\n        /**\n         * 判断是否需要对Flash事件做代理，\n         * 主要fix flash上的鼠标事件没法响应到DOM节点上的问题\n         * @return {Boolean} 是否做代理\n         */\n        _h.__canFlashEventBubble = function(_wmode){\n            return !0;\n        };\n\n    });\n\n    NEJ.patch('WV',function(){\n        /**\n         * 判断是否需要对Flash事件做代理，\n         * 主要fix flash上的鼠标事件没法响应到DOM节点上的问题\n         * @return {Boolean} 是否做代理\n         */\n        _h.__canFlashEventBubble = function(_wmode){\n            return !0;\n        };\n\n    });\n\n    return _h;\n});\n"
  },
  {
    "path": "src/util/flash/test/flash.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>flash测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit xdr test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./flash.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/flash/test/flash.test.js",
    "content": "NEJ.define(['util/flash/flash'],function(){\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v');\n    test('flash',function(){\n        expect(0)\n        var _flash = _e._$flash({\n              src:'../../../../res/nej_upload_image.swf',\n              hidden:false,\n              parent:document.body,\n              width:900,\n              height:600,\n              params:{\n                  flashvars:'',\n                  wmode:'transparent',\n                  allowscriptaccess:'always'\n              },\n              onready:function(_flash){\n              },\n              oncustom:function(_event){\n              }\n        });\n    });\n});"
  },
  {
    "path": "src/util/focus/focus.js",
    "content": "/*\n * ------------------------------------------\n * 聚焦效果接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/focus/focus */\nNEJ.define([\n    'base/global',\n    'base/util',\n    'base/element',\n    '{platform}focus.js',\n    'base/chain'\n],function(NEJ,_u,_e,_h,_x,_p,_o,_f,_r){\n    /**\n     * 节点focus行为，提供两种模式支持\n     *\n     * * 0 - 聚焦添加效果，失焦去除效果，高版本使用:focus样式处理\n     * * 1 - 聚焦添加效果，失焦时只有在当前输入框没有内容时去除效果\n     *\n     * 样式举例\n     * ```css\n     *   input:focus,input.js-focus{border:1px solid #f00;}\n     *   input{color:#aaa;background:#eee;}\n     *   .js-focus-0{color:#000;background-color:#fff;}\n     * ```\n     *\n     * 结构举例\n     * ```html\n     *   <form>\n     *     <!-- 可以使用data-focus指定聚焦时样式名称 -->\n     *     <!-- 可以使用data-mode指定聚焦模式 -->\n     *     <!-- 通过data-focus/data-mode指定的参数优先级高于接口调用时输入参数 -->\n     *     <input id=\"xxx\" type=\"text\" data-focus=\"js-focus-0\" data-mode=\"1\"/>\n     *     <!-- 节点没有指定参数 -->\n     *     <input id=\"yyy\" type=\"text\"/>\n     *   </form>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'util/focus/focus'\n     *   ],function(_e){\n     *       // 参数已在节点data-属性中指定\n     *       _e._$focus('xxx');\n     *\n     *       // 参数没有指定，通过输入传递，仅指定样式名称\n     *       _e._$focus('yyy','js-focus-1');\n     *\n     *       // 参数没有指定，通过输入传递，仅指定聚焦模式\n     *       _e._$focus('yyy',1);\n     *\n     *       // 参数没有指定，通过输入传递，同时指定样式名称和聚焦模式\n     *       _e._$focus('yyy',{clazz:'js-focus-2',mode:1});\n     *   });\n     * ```\n     *\n     * @method   module:util/focus/focus._$focus\n     * @param    {String|Node} arg0  - 节点\n     * @param    {Object}      arg1  - 配置参数\n     * @property {Number}      mode  - 模式选择，默认为0\n     * @property {String}      clazz - 聚焦样式，默认js-focus\n     * @return   {Void}\n     */\n    /**\n     * @method CHAINABLE._$focus\n     * @see module:util/focus/focus._$focus\n     */\n    _p._$focus = function(_element,_options){\n        _element = _e._$get(_element);\n        if (!!_element){\n            var _mode = 0,\n                _clazz = 'js-focus';\n            // check param\n            if (_u._$isNumber(_options)){\n                _mode = _options;\n            }else if(_u._$isString(_options)){\n                _clazz = _options;\n            }else if(_u._$isObject(_options)){\n                _mode = _options.mode||_mode;\n                _clazz = _options.clazz||_clazz;\n            }\n            // check data- attribute\n            var _value = parseInt(\n                _e._$dataset(_element,'mode')\n            );\n            if (!isNaN(_value)){\n                _mode = _value;\n            }\n            _value = _e._$dataset(_element,'focus');\n            if (!!_value){\n                _clazz = _value;\n            }\n            // do focus\n            _h.__focusElement(_element,_mode,_clazz);\n        }\n    };\n    // for chainable method\n    _x._$merge(_p);\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.e'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/focus/platform/focus.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   \n * ------------------------------------------\n */\nNEJ.define([\n    'base/event',\n    'base/element'\n],function(_v,_e,_p,_o,_f,_r){\n    /**\n     * 节点focus行为\n     * @param  {String|Node} 节点\n     * @param  {Number}      模式\n     * @param  {String}      样式\n     * @return {Void}\n     */\n    _p.__focusElement = (function(){\n        // do blur check\n        var _onBlur = function(_clazz,_event){\n            var _element = _v._$getElement(_event);\n            if (!_element.value)\n                _e._$delClassName(_element,_clazz);\n        };\n        // do focus\n        var _onFocus = function(_clazz,_event){\n            _e._$addClassName(\n                _v._$getElement(_event),_clazz);\n        };\n        return function(_element,_mode,_clazz){\n            if (_mode==1){\n                _v._$addEvent(\n                    _element,'blur',\n                    _onBlur._$bind(null,_clazz)\n                );\n            }\n            if (_mode==1||_mode==-1){\n                _v._$addEvent(\n                    _element,'focus',\n                    _onFocus._$bind(null,_clazz)\n                );\n            }\n            // other do nothing, use css :focus\n        };\n    })();\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/focus/platform/focus.patch.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   \n * ------------------------------------------\n */\nNEJ.define([\n    './focus.js',\n    'base/event',\n    'base/element'\n],function(_h,_v,_e,_p,_o,_f,_r){\n    // TR 2.0 - IE 6\n    // TR 3.0 - IE 7\n    // TR 4.0 - IE 8\n    // TR 5.0 - IE 9\n    // TR 6.0 - IE 10\n    // TR 7.0 - IE 11\n    \n    // for ie7-\n    NEJ.patch('TR<=3.0',function(){\n        /**\n         * 节点focus行为\n         * @param  {String|Node} 节点\n         * @param  {Number}      模式\n         * @param  {String}      样式\n         * @return {Void}\n         */\n        _h.__focusElement = (function(){\n            // remove classname onblur\n            var _onBlur = function(_clazz,_event){\n                _e._$delClassName(\n                    _v._$getElement(_event),_clazz\n                );\n            };\n            return _h.__focusElement._$aop(\n                function(_event){\n                    // patch ie6-7 :focus\n                    var _args = _event.args;\n                    if (_args[1]!=1){\n                        _v._$addEvent(\n                            _args[0],'blur',\n                            _onBlur._$bind(null,_args[2])\n                        );\n                        _args[1] = -1;\n                    }\n                }\n            );\n        })();\n    });\n    \n    return _h;\n});\n"
  },
  {
    "path": "src/util/focus/test/focus.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>focus测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n        <style type=\"text/css\">\n            .js-focus-2{background:red;}\n        </style>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit xdr test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <input id=\"abc\" type=\"text\" data-focus=\"js-focus-2\" data-mode=\"1\"/>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./focus.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/focus/test/focus.test.js",
    "content": "NEJ.define(['util/focus/focus'],function(){\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v');\n    test('focus',function(){\n        expect(0)\n        _e._$focus('abc',{clazz:'js-focus-2',mode:0});\n    });\n});"
  },
  {
    "path": "src/util/form/demo/form.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - Form表单控件</title>\n    <meta charset=\"utf-8\" />\n    <style>\n      .js-invalid{border:1px solid #f00;}\n    </style>\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n  </head>\n  <body>\n    <input type=\"button\" value=\"test\" id=\"xyz\"/>\n    <textarea name=\"ntp\" id=\"abc\">\n        <form>\n          <input type=\"text\" name=\"aab\" data-type=\"date\" data-format=\"yyyy-MM-dd HH:mm:ss\" data-message=\"输入正确的日期\"/>\n          <div>\n              <input type=\"text\" name=\"xyz\" data-abc=\"true\" />\n              <select name=\"abc\" data-type=\"number\">\n                  <option value=\"1\">1</option>\n                  <option value=\"2\">2</option>\n                  <option value=\"3\">3</option>\n                  <option value=\"4\">4</option>\n              </select>\n              <select name=\"def\" multiple=\"true\" data-type=\"number\">\n                  <option value=\"1\">1</option>\n                  <option value=\"2\">2</option>\n                  <option value=\"3\">3</option>\n                  <option value=\"4\">4</option>\n              </select>\n          </div>\n          <input type=\"button\" name=\"btn\" value=\"ok\"/>\n        </form>\n    </textarea>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            'base/event',\n            'base/element',\n            'util/template/tpl',\n            '../form.js'\n        ],function(_v,_ex,_e,_t){\n            _e._$parseTemplate('abc');\n            var _webform;\n            var _form = _e._$getNodeTemplate('abc');\n            var _fbox = _form.getElementsByTagName('DIV')[0];\n            _v._$addEvent(_form.btn,'click',function(){\n                if (_webform._$checkValidity()){\n                    var _data = _webform._$data();\n                    console.log(_data);\n                    log('submit form to server');\n                }\n            });\n            _webform = _t._$$WebForm._$allocate({\n                form:_form,\n                attr:{\n                    abc:function(_node,_options){\n                        console.log('xxx');\n                    }\n                }\n            });\n            document.body.appendChild(_form);\n            \n            _webform._$setValue('def',[2,3]);\n            \n            _v._$addEvent(\n                'xyz','click',function(_event){\n                    _fbox.innerHTML = '<input type=\"text\" name=\"jjj\" data-required=\"true\"/>';\n                }\n            );\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/form/form.js",
    "content": "/*\n * ------------------------------------------\n * WEB表单封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/form/form */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'base/util',\n    'util/event',\n    'util/focus/focus',\n    'util/counter/counter',\n    'util/placeholder/placeholder'\n],function(NEJ,_k,_e,_v,_u,_t,_t2,_t0,_t1,_p,_o,_f,_r,_pro){\n    /**\n     * WEB表单验证封装对象，HTML代码中支持以下属性配置：\n     * \n     * | 名称 | 类型 | 说明 |\n     * | :--- | :--- | :--- |\n     * | data-focus-mode | 0/1                   | 聚焦模式，仅在form节点上设置，见_$focus |\n     * | data-focus      | true/false            | 聚焦时检测提示信息，对于需验证的表单控件默认已支持此属性 |\n     * | data-auto-focus | true/false            | 自动聚焦项，多个表单项设置了该属性仅第一项有效 |\n     * | data-counter    | true/false            | 是否需要显示计数信息，必须同时设置data-max-length或者maxlength |\n     * | data-ignore     | true/false            | 临时忽略失去焦点验证，可动态控制验证触发时机 |\n     * | data-message    | String                | 验证出错提示信息，多个提示信息可以通过配置或者回调事件定制提示内容 |\n     * | data-tip        | String                | 默认提示信息，正常输入状态时的提示信息 |\n     * | data-required   | true/false            | 必填项，对于checkbox/radio的required表示必须选中 |\n     * | data-type       | url/email/date/number | 输入内容预订类型格式匹配 |\n     * | data-time       | String                | 格式：HH:mm:ss.ms，对于data-type为date类型的字段，取出日期值时设定时间为此值 |\n     * | data-pattern    | RegExp                | 正则匹配表达式，字符串格式 |\n     * | data-min        | String/Number         | 输入值必须大于此设置，适用于number/date型 |\n     * | data-max        | String/Number         | 输入值必须小于此设置，适用于number/date型 |\n     * | data-format     | String                | 规范date类型的格式，用/或者-来连接日期，用：来连接时间，至少应该有MM/dd/yyyy，默认值为yyyy-MM-dd，适用于date型(yyyy:年，MM:月，dd:日，HH:小时，mm:分钟,ss:秒) |\n     * | data-max-length | Number                | 输入长度必须小于此设置，一个中文算两个字符，适用于text/textarea |\n     * | data-min-length | Number                | 输入长度必须大于此设置，一个中文算两个字符，适用于text/textarea |\n     * | maxlength       | Number                | 输入长度必须小于此设置，一个中文算一个字符，适用于text/textarea |\n     * | minlength       | Number                | 输入长度必须大于此设置，一个中文算一个字符，适用于text/textarea |\n     *\n     * 结构举例\n     * ```html\n     * <!-- form节点添加data-focus-mode属性 -->\n     * <form id=\"webForm\" data-focus-mode=\"1\">\n     *   <!-- 必须设置值 -->\n     *   <input name=\"n00\" type=\"text\" data-auto-focus=\"true\" data-required=\"true\" data-message=\"必须输入xxx！\" data-tip=\"这是对xxx的说明！\"/>\n     *   <select name=\"n01\" data-required=\"true\" data-message=\"必须选择xxx！\">\n     *     <option>please select city</option>\n     *     <option value=\"0\">Hangzhou</option>\n     *     <option value=\"1\">Shanghai</option>\n     *   </select>\n     *   <input type=\"checkbox\" data-required=\"true\" data-message=\"必须同意xxx！\"/>\n     *   <input type=\"radio\" data-required=\"true\" data-message=\"必须选中xxx！\"/>\n     *   <!-- 输入URL地址、Email地址、日期、数字 -->\n     *   <input name=\"n10\" type=\"text\" data-type=\"url\" data-message=\"URL地址不合法！\"/>\n     *   <input name=\"n11\" type=\"text\" data-type=\"email\" data-message=\"Email地址不合法！\"/>\n     *   <input name=\"n12\" type=\"text\" data-type=\"date\" data-format=\"yyyy-MM-dd HH:mm:ss\" data-message=\"日期格式不正确！\"/>\n     *   <input name=\"n12\" type=\"text\" data-type=\"number\" data-message=\"只能输入数字！\"/>\n     *   <!-- 正则匹配输入信息，注意pattern值必须符合正则表达式规则 -->\n     *   <input name=\"n20\" type=\"text\" data-pattern=\"^[\\\\d]+$\" data-message=\"输入内容必须符合xxx！\"/>\n     *   <!-- 限制输入长度 -->\n     *   <input name=\"n30\" type=\"text\" maxlength=\"100\" data-message=\"长度超过限制！\"/>\n     *   <textarea name=\"n31\" maxlength=\"100\" data-message=\"长度超过限制！\"></textarea>\n     *   <input name=\"n32\" type=\"text\" data-max-length=\"100\" data-message=\"长度超过限制！\"/>\n     *   <textarea name=\"n33\" data-max-length=\"100\" data-message=\"长度超过限制！\"></textarea>\n     *   <input name=\"n34\" type=\"text\" minlength=\"100\" data-message=\"长度必须达到xxx！\"/>\n     *   <textarea name=\"n35\" minlength=\"100\" data-message=\"长度必须达到xxx！\"></textarea>\n     *   <input name=\"n36\" type=\"text\" data-min-length=\"100\" data-message=\"长度必须达到xxx！\"/>\n     *   <textarea name=\"n37\" data-min-length=\"100\" data-message=\"长度必须达到xxx！\"></textarea>\n     *   <!-- 限制最小值/最大值 -->\n     *   <input name=\"n40\" type=\"text\" data-type=\"number\" data-min=\"10\"/>\n     *   <input name=\"n41\" type=\"text\" data-type=\"number\" data-max=\"100\"/>\n     *   <input name=\"n42\" type=\"text\" data-type=\"number\" data-min=\"10\" data-max=\"100\"/>\n     *   <input name=\"n43\" type=\"text\" data-type=\"date\" data-min=\"2010-08-10\"/>\n     *   <input name=\"n44\" type=\"text\" data-type=\"date\" data-max=\"now\"/>\n     *   <input name=\"n45\" type=\"text\" data-type=\"date\" data-min=\"now\" data-max=\"2050-10-10\"/>\n     * </form>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/form/form'\n     * ],function(_t){\n     *     // 分配表单验证控件实例\n     *     var _form = _t._$$WebForm._$allocate({\n     *         form:'webForm',\n     *         message:{\n     *             'password-1':'必须输入密码！',\n     *             'password100':'密码强度不够',\n     *             'password101':'两次密码不一致',\n     *             'pass':'<span class=\"pass\">ok</span>'\n     *         }\n     *     });\n     *    \n     *     // 验证表单后提交\n     *     if (_form._$checkValidity()){\n     *         _form._$submit();\n     *     }\n     *    \n     *     // 或者在验证完表单的配置项后再做表单的其他项验证\n     *     if (_form._$checkValidity()){\n     *         // TODO other form check\n     *         // 验证过程可以调用一下接口显示错误信息\n     *         // _form._$showMsgError('n30','invalid message！');\n     *         // 验证过程可以调用一下接口显示通过信息\n     *         // _form._$showMsgPass('n31','ok！');\n     *         _form._$submit();\n     *         // 使用ajax请求的话可以通过_form._$data()获取表单信息\n     *         doAjaxRequest('/api/form',_form._$data());\n     *     }\n     *    \n     *     // 通过回调自定义提示信息示例代码：\n     *     var _form = _t._$$WebForm._$allocate({\n     *         form:'webForm',\n     *         oninvalid:function(_event){\n     *             // check _event.target and _event.code\n     *             if (_event.target.name=='password'&&_event.code==-1){\n     *                 // 通过设置_event.value设置提示信息\n     *                 _event.value = '必须输入密码！';\n     *             }\n     *             // TODO other check\n     *         },\n     *         onvalid:function(_event){\n     *             // 自定义验证通过提示信息，对应的节点信息_event.target\n     *             _event.value = '<span class=\"pass\">pass</span>'\n     *         }\n     *     });\n     *     \n     *     // 通过回调自定义验证规则示例代码：\n     *     var _form = _t._$$WebForm._$allocate({\n     *         form:'webForm',\n     *         oncheck:function(_event){\n     *             // check _event.target\n     *             if (_event.target.name=='password'){\n     *                 // 通过_event.value返回验证结果\n     *                 // 验证结果必须大于0的值（保留所有小于0的返回值）\n     *                 // 也可以返回对象，_event.value = {a:'aaaa',b:'bbbb'}; \n     *                 // 这里的a，b可以在oninvalid时输入的_event中取到\n     *                 _event.value = doCheckPassword(_event.target.value); // 100\n     *             }\n     *             // TODO other check\n     *         },\n     *         oninvalid:function(_event){\n     *             // check _event.target and _event.code\n     *             if (_event.target.name=='password'&&_event.code==100){\n     *                 // 通过设置_event.value设置提示信息\n     *                 _event.value = '密码强度太弱！';\n     *             }\n     *             // TODO other check\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @class    module:util/form/form._$$WebForm\n     * @extends  module:util/event._$$EventTarget\n     *\n     * @param    {Object}      config  - 配置参数\n     * @property {String|Node} form    - 表单节点\n     * @property {String}      invalid - 验证未通过时添加在表单元素上的样式名称，默认为js-invalid\n     * @property {String}      holder  - 如果有placeholder，则可以指定样式名称，默认为js-placeholder\n     * @property {String}      focus   - 如果有聚焦效果，则可以通过指定该样式名称，默认为js-focus\n     * @property {String}      tip     - 提示信息效果样式名称，默认为js-tip\n     * @property {String}      pass    - 提示信息效果样式名称，默认为js-pass\n     * @property {String}      error   - 提示信息效果样式名称，默认为js-error\n     * @property {Object}      type    - 类型验证扩展，主要扩展data-type值的验证规则，{type:regexp,type:function}\n     * @property {Object}      attr    - 验证属性扩展，主要扩展自定义data-xxx的验证规则，{xxx:function}\n     * @property {Object}      message - 提示信息内容，{key:value}，\n     *                                   错误信息key规则：节点名称+错误代码，\n     *                                   如 'username-1':'必须输入用户名！'\n     *                                   表示username输入框没有输入内容时错误提示信息为'必须输入用户名！'，\n     *                                   默认错误信息key规则：节点名称+'-error'，如username-error，\n     *                                   提示信息key规则：节点名称+'-tip'，如username-tip，\n     *                                   成功信息key规则：节点名称+'-pass'，如username-pass，\n     *                                   默认成功信息key：pass\n     */\n    /**\n     * 对于无法通过配置验证的控件会回调外界辅助验证\n     * \n     * @event    module:util/form/form._$$WebForm#oncheck\n     * @param    {Object} event  - 验证基本信息\n     * @property {Node}   target - 当前验证节点\n     * @property {Node}   form   - 表单对象\n     * @property {Number} value  - 验证返回结果\n     */\n    /**\n     * 验证未通过触发事件，错误类型对照表\n     * \n     * | 错误码 | 说明 |\n     * | :---   | :--- |\n     * | -1     | 必填项未填值 |\n     * | -2     | 类型不匹配，如email, url类型 |\n     * | -3     | 值不符合提供的规则 |\n     * | -4     | 超过最大长度限制 |\n     * | -5     | 未达到最小长度 |\n     * | -6     | 未达到给定范围的最小值 |\n     * | -7     | 超出给定范围的最大值 |\n     * \n     * @event    module:util/form/form._$$WebForm#oninvalid\n     * @param    {Object} event  - 验证基本信息\n     * @property {Node}   target - 当前验证节点\n     * @property {Number} code   - 错误标识\n     */\n    /**\n     * 通过验证提示信息\n     * \n     * @event    module:util/form/form._$$WebForm#onvalid\n     * @param    {Object} event  - 验证基本信息\n     * @property {Node}   target - 当前验证节点\n     */\n    /**\n     * 回车触发事件\n     * \n     * @event   module:util/form/form._$$WebForm#onenter\n     * @param   {Event} event 事件信息\n     */\n    _p._$$WebForm = _k._$klass();\n    _pro = _p._$$WebForm._$extend(_t._$$EventTarget);\n    /**\n     * 控件初始化\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__super();\n        this.__wopt = {\n            tp:{nid:'js-nej-tp'},\n            ok:{nid:'js-nej-ok'},\n            er:{nid:'js-nej-er'}\n        };\n    };\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__form = document.forms[_options.form]||\n                     _e._$get(_options.form);\n        this.__doInitDomEvent([[\n            this.__form,'enter',\n            this._$dispatchEvent._$bind(this,'onenter')\n        ]]);\n        this.__message = _options.message||{};\n        this.__message.pass = this.__message.pass||'&nbsp;';\n        // focus options\n        var _mode = this.__dataset(\n                    this.__form,'focusMode',1);\n        if (!isNaN(_mode)){\n            this.__fopt = {\n                mode:_mode,\n                clazz:_options.focus\n            };\n        }\n        // save class name\n        this.__holder = _options.holder;\n        this.__wopt.tp.clazz = 'js-mhd '+(_options.tip||'js-tip');\n        this.__wopt.ok.clazz = 'js-mhd '+(_options.pass||'js-pass');\n        this.__wopt.er.clazz = 'js-mhd '+(_options.error||'js-error');\n        this.__invalid = _options.invalid||'js-invalid';\n        // init valid rule\n        this.__doInitValidRule(_options);\n        // refresh validate node\n        this._$refresh();\n        // auto focus node\n        if (!!this.__fnode){\n            this.__fnode.focus();\n        }\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        this._$reset();\n        delete this.__message;\n        delete this.__fnode;\n        delete this.__vinfo;\n        delete this.__xattr;\n        delete this.__form;\n        delete this.__treg;\n        delete this.__vfun;\n    };\n    /**\n     * 取节点自定义数据值\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__dataset\n     * @param  {String} arg0 - 自定义属性名\n     * @param  {Number} arg1 - 类型，0-字符，1-数值，2-布尔，3-日期\n     * @return {String}        值\n     */\n    _pro.__dataset = function(_node,_attr,_type){\n        var _value = _e._$dataset(_node,_attr);\n        switch(_type){\n            case 1: return parseInt(_value,10);\n            case 2: return (_value||'').toLowerCase()=='true';\n            case 3: return this.__doParseDate(_value);\n        }\n        return _value;\n    };\n    /**\n     * 根据类型转数值\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__number\n     * @param  {String} arg0 - 值\n     * @param  {String} arg1 - 类型\n     * @return {Number}        数值\n     */\n    _pro.__number = function(_value,_type,_time){\n        if (_type=='date'){\n            return this.__doParseDate(_value,_time);\n        }\n        return parseInt(_value,10);\n    };\n    /**\n     * 判断节点是否需要验证\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__isValidElement\n     * @param  {Node}    arg0 - 节点\n     * @return {Boolean}        是否需要验证\n     */\n    _pro.__isValidElement = (function(){\n        var _reg1 = /^button|submit|reset|image|hidden|file$/i;\n        return function(_node){\n            // with name attr\n            // not button\n            _node = this._$get(_node)||_node;\n            var _type = _node.type;\n            return !!_node.name&&\n                    !_reg1.test(_node.type||'');\n        };\n    })();\n    /**\n     * 判断节点是否需要验证\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__isValidElement\n     * @param  {Node}    arg0 - 节点\n     * @return {Boolean}        是否需要验证\n     */\n    _pro.__isValueElement = (function(){\n        var _reg1 = /^hidden$/i;\n        return function(_node){\n            if (this.__isValidElement(_node))\n                return !0;\n            _node = this._$get(_node)||_node;\n            var _type = _node.type||'';\n            return _reg1.test(_type);\n        };\n    })();\n    /**\n     * 解析日期值\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__doParseDate\n     * @param  {String} arg0 - 日期字符串\n     * @return {Number}        日期毫秒数\n     */\n    _pro.__doParseDate = (function(){\n        var _reg0 = /[:\\.]/;\n        return function(_value,_time){\n            if ((_value||'').toLowerCase()=='now')\n                return +new Date;\n            var _date = _u._$var2date(_value);\n            if (!!_date&&!_reg0.test(_value)){\n                // HH:mm:ss.ms\n                var _arr = (_time||'').split(_reg0);\n                _date.setHours(\n                    parseInt(_arr[0],10)||0,\n                    parseInt(_arr[1],10)||0,\n                    parseInt(_arr[2],10)||0,\n                    parseInt(_arr[3],10)||0\n                );\n            }\n            return +_date;\n        };\n    })();\n    /**\n     * 解析字符类型规则属性\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__doCheckString\n     * @param  {String} arg0 - 规则标识\n     * @param  {String} arg1 - 规则属性\n     * @return {Void}\n     */\n    _pro.__doCheckString = function(_id,_name){\n        var _rule = this.__vfun[_name],\n            _value = this.__dataset(_id,_name);\n        if (!_value||!_rule) return;\n        this.__doPushValidRule(_id,_rule);\n        this.__doSaveValidInfo(_id,_name,_value);\n    };\n    /**\n     * 解析正则类型规则属性\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__doCheckPattern\n     * @param  {String} arg0 - 规则标识\n     * @param  {String} arg1 - 规则属性\n     * @return {Void}\n     */\n    _pro.__doCheckPattern = function(_id,_name){\n        try{\n            var _pattern = this.__dataset(_id,_name);\n            if (!_pattern) return;\n            var _value = new RegExp(_pattern);\n            this.__doSaveValidInfo(_id,_name,_value);\n            this.__doPushValidRule(_id,this.__vfun[_name]);\n        }catch(e){\n            // ignore exception\n        }\n    };\n    /**\n     * 解析布尔类型规则属性\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__doCheckBoolean\n     * @param  {String} arg0 - 规则标识\n     * @param  {String} arg1 - 规则属性\n     * @return {Void}\n     */\n    _pro.__doCheckBoolean = function(_id,_name){\n        var _rule = this.__vfun[_name];\n        if (!!_rule&&this.__dataset(_id,_name,2)){\n            this.__doPushValidRule(_id,_rule);\n        }\n    };\n    /**\n     * 解析数值类型规则属性\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__doCheckNumber\n     * @param  {String} arg0 - 规则标识\n     * @param  {String} arg1 - 规则属性\n     * @param  {String} arg2 - 规则值\n     * @return {Void}\n     */\n    _pro.__doCheckNumber = function(_id,_name,_value){\n        _value = parseInt(_value,10);\n        if (isNaN(_value)) return;\n        this.__doSaveValidInfo(_id,_name,_value);\n        this.__doPushValidRule(_id,this.__vfun[_name]);\n    };\n    /**\n     * 解析dataset中数值类型规则属性\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__doCheckDSNumber\n     * @param  {String} arg0 - 规则标识\n     * @param  {String} arg1 - 规则属性\n     * @return {Void}\n     */\n    _pro.__doCheckDSNumber = function(_id,_name){\n        this.__doCheckNumber(_id,_name,this.__dataset(_id,_name));\n    };\n    /**\n     * 解析属性中数值类型规则属性\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__doCheckATNumber\n     * @param  {String} arg0 - 规则标识\n     * @param  {String} arg1 - 规则属性\n     * @return {Void}\n     */\n    _pro.__doCheckATNumber = function(_id,_name){\n        this.__doCheckNumber(_id,_name,_e._$attr(_id,_name));\n    };\n    /**\n     * 解析dataset中数值类型规则属性\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__doCheckTPNumber\n     * @param  {String} arg0 - 规则标识\n     * @param  {String} arg1 - 规则属性\n     * @return {Void}\n     */\n    _pro.__doCheckTPNumber = function(_id,_name,_type){\n        var _value = this.__number(\n                     this.__dataset(_id,_name),\n                     this.__dataset(_id,'type'));\n        this.__doCheckNumber(_id,_name,_value);\n    };\n    /**\n     * 验证扩展属性\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__doCheckCustomAttr\n     * @param  {String} arg0 - 规则标识\n     * @return {Void}\n     */\n    _pro.__doCheckCustomAttr = function(_id){\n        _u._$loop(\n            this.__xattr,function(v,_name){\n                var _value = _e._$dataset(_id,_name);\n                if (_value!=null){\n                    this.__doSaveValidInfo(_id,_name,_value);\n                    this.__doPushValidRule(_id,this.__vfun[_name]);\n                }\n            },this\n        );\n    };\n    /**\n     * 准备表单元素验证信息\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__doPrepareElement\n     * @param  {Node} arg0 - 表单元素节点\n     * @return {Void}\n     */\n    _pro.__doPrepareElement = (function(){\n        var _reg0 = /^input|textarea$/i,\n            _reg1 = /[:\\.]/;\n        // onfocus\n        var _onFocus = function(_event){\n            this._$showTip(_v._$getElement(_event));\n        };\n        // onblur\n        var _onBlur = function(_event){\n            var _node = _v._$getElement(_event);\n            if (!this.__dataset(_node,'ignore',2)){\n                this.__doCheckValidity(_node);\n            }\n        };\n        return function(_node){\n            // check auto focus node\n            if (this.__dataset(\n                      _node,'autoFocus',2))\n                this.__fnode = _node;\n            // check placeholder\n            var _holder = _e._$attr(_node,'placeholder');\n            if (!!_holder&&_holder!='null')\n                _t1._$placeholder(_node,this.__holder);\n            // check focus\n            if (!!this.__fopt&&\n                _reg0.test(_node.tagName))\n                _t2._$focus(_node,this.__fopt);\n            // check validate condition\n            var _id = _e._$id(_node);\n            // type check\n            // pattern check\n            // required check\n            // max length\n            // min length\n            // cn max length\n            // cn min length\n            // min value check\n            // max value check\n            this.__doCheckBoolean(_id,'required');\n            this.__doCheckString(_id,'type');\n            this.__doCheckPattern(_id,'pattern');\n            this.__doCheckATNumber(_id,'maxlength');\n            this.__doCheckATNumber(_id,'minlength');\n            this.__doCheckDSNumber(_id,'maxLength');\n            this.__doCheckDSNumber(_id,'minLength');\n            this.__doCheckTPNumber(_id,'min');\n            this.__doCheckTPNumber(_id,'max');\n            this.__doCheckCustomAttr(_id);\n            // check date time\n            var _time = _e._$dataset(_id,'time');\n            if (!!_time){\n                this.__doSaveValidInfo(_id,'time',_time);\n            }\n            // save message content\n            var _name = _node.name;\n            this.__message[_name+'-tip'] = this.__dataset(_node,'tip');\n            this.__message[_name+'-error'] = this.__dataset(_node,'message');\n            this._$showTip(_node);\n            // node counter\n            var _info = this.__vinfo[_id],\n                _data = (_info||_o).data||_o,\n                _need = this.__dataset(_node,'counter',2);\n            if (_need&&(_data.maxlength||_data.maxLength)){\n                _t0._$counter(_id,{nid:this.__wopt.tp.nid,clazz:'js-counter'});\n            }\n            // node need validate\n            if (!!_info&&_reg0.test(_node.tagName)){\n                this.__doInitDomEvent([\n                    [_node,'focus',_onFocus._$bind(this)],\n                    [_node,'blur',_onBlur._$bind(this)]\n                ]);\n            }else if(this.__dataset(_node,'focus',2)){\n                this.__doInitDomEvent([\n                    [_node,'focus',_onFocus._$bind(this)],\n                ]);\n            }\n        };\n    })();\n    /**\n     * 初始化验证规则\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__doInitValidRule\n     * @param  {Object} arg0 - 配置信息\n     * @return {Void}\n     */\n    _pro.__doInitValidRule = (function(){\n        // type regexp map\n        var _rmap = {\n                number:/^[\\d]+$/i,\n                // xxx://xx.xx.xx/a/b\n                url:/^[a-z]+:\\/\\/(?:[\\w-]+\\.)+[a-z]{2,6}.*$/i,\n                // xxx@xx.xx.xxx\n                email:/^[\\w-\\.]+@(?:[\\w-]+\\.)+[a-z]{2,6}$/i,\n                // xx-x-xx or xxxx-xx-x\n                date:function(v,node){\n                    var format = this.__dataset(node,'format')||'yyyy-MM-dd';\n                    return !v||(!isNaN(this.__doParseDate(v)) && _u._$format(this.__doParseDate(v),format) == v);\n                }\n            };\n        // validate function map\n        var _vfun = {\n            // value require for text\n            // checked require for checkbox or radio\n            required:function(_node){\n                var _type = _node.type,\n                    _novalue = !_node.value,\n                    _nocheck = (_type=='checkbox'||\n                                _type=='radio')&&!_node.checked;\n                if (_nocheck||_novalue) return -1;\n            },\n            // type supported in _regmap\n            type:function(_node,_options){\n                var _reg = this.__treg[_options.type],\n                    _val = _node.value.trim(),\n                    _tested = !!_reg.test&&!_reg.test(_val),\n                    _funced = _u._$isFunction(_reg)&&!_reg.call(this,_val,_node);\n                if (_tested||_funced) return -2;\n            },\n            // pattern check\n            pattern:function(_node,_options){\n                if (!_options.pattern.test(_node.value))\n                    return -3;\n            },\n            // maxlength check\n            maxlength:function(_node,_options){\n                if (_node.value.length>_options.maxlength)\n                    return -4;\n            },\n            // minlength check\n            minlength:function(_node,_options){\n                if (_node.value.length<_options.minlength)\n                    return -5;\n            },\n            // data-max-length check\n            maxLength:function(_node,_options){\n                if (_u._$length(_node.value)>_options.maxLength)\n                    return -4;\n            },\n            // data-min-length check\n            minLength:function(_node,_options){\n                if (_u._$length(_node.value)<_options.minLength)\n                    return -5;\n            },\n            // min value check\n            min:function(_node,_options){\n                var _number = this.__number(\n                    _node.value,\n                    _options.type,\n                    _options.time\n                );\n                if (isNaN(_number)||\n                   _number<_options.min)\n                    return -6;\n            },\n            // max value check\n            max:function(_node,_options){\n                var _number = this.__number(\n                    _node.value,\n                    _options.type,\n                    _options.time\n                );\n                if (isNaN(_number)||\n                   _number>_options.max)\n                    return -7;\n            }\n        };\n        // merge extend\n        var _doMerge = function(_smap,_new,_key,_dmap){\n            var _old = _smap[_key];\n            if (_u._$isFunction(_new)&&\n                _u._$isFunction(_old)){\n                _smap[_key] = _old._$aop(_new);\n                return;\n            }\n            _smap[_key] = _new;\n        };\n        return function(_options){\n            this.__treg = NEJ.X({},_rmap);\n            _u._$loop(\n                _options.type,\n                _doMerge._$bind(null,this.__treg)\n            );\n            this.__vfun = NEJ.X({},_vfun);\n            this.__xattr = _options.attr;\n            _u._$loop(\n                this.__xattr,\n                _doMerge._$bind(null,this.__vfun)\n            );\n        };\n    })();\n    /**\n     * 添加验证规则\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__doPushValidRule\n     * @param  {String}   arg0 - 规则标识\n     * @param  {Function} arg1 - 验证规则\n     * @return {Void}\n     */\n    _pro.__doPushValidRule = function(_id,_valid){\n        if (!_u._$isFunction(_valid)) return;\n        var _info = this.__vinfo[_id];\n        if (!_info||!_info.func){\n            _info = _info||{};\n            _info.func = [];\n            this.__vinfo[_id] = _info;\n        }\n        _info.func.push(_valid);\n    };\n    /**\n     * 缓存验证信息\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__doSaveValidInfo\n     * @param  {String}   arg0 - 验证标识\n     * @param  {String}   arg1 - 信息标识\n     * @param  {Variable} arg2 - 信息内容\n     * @return {Void}\n     */\n    _pro.__doSaveValidInfo = function(_id,_name,_value){\n        if (!_name) return;\n        var _info = this.__vinfo[_id];\n        if (!_info||!_info.data){\n            _info = _info||{};\n            _info.data = {};\n            this.__vinfo[_id] = _info;\n        }\n        _info.data[_name] = _value;\n    };\n    /**\n     * 验证节点\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__doCheckValidity\n     * @param  {String|Node} arg0 - 节点\n     * @return {Boolean}            是否通过验证\n     */\n    _pro.__doCheckValidity = function(_node){\n        // check node validate\n        _node = this._$get(_node)||_node;\n        if (!_node){\n            return !0;\n        }\n        // check validate information\n        var _info = this.__vinfo[_e._$id(_node)];\n        if (!_info&&this.__isValidElement(_node)){\n            this.__doPrepareElement(_node);\n            _info = this.__vinfo[_e._$id(_node)];\n        }\n        if (!_info){\n            return !0;\n        }\n        var _result;\n        // check condition\n        _u._$forIn(_info.func,\n            function(_func){\n                _result = _func.call(this,_node,_info.data);\n                return _result!=null;\n            },this);\n        // check custom validate\n        if (_result==null){\n            var _event = {target:_node,form:this.__form};\n            this._$dispatchEvent('oncheck',_event);\n            _result = _event.value;\n        }\n        // dispatch validate event\n        var _event = {target:_node,form:this.__form};\n        if (_result!=null){\n            // merge oncheck result\n            if (_u._$isObject(_result)){\n                _u._$merge(_event,_result);\n            }else{\n                _event.code = _result;\n            }\n            this._$dispatchEvent('oninvalid',_event);\n            if (!_event.stopped){\n                this._$showMsgError(\n                    _node,_event.value||\n                    this.__message[_node.name+_result]\n                );\n            }\n        }else{\n            this._$dispatchEvent('onvalid',_event);\n            if (!_event.stopped){\n                this._$showMsgPass(_node,_event.value);\n            }\n        }\n        return _result==null;\n    };\n    /**\n     * 显示信息\n     * \n     * @protected\n     * @method module:util/form/form._$$WebForm#__doShowMessage\n     * @param  {String|Node} arg0 - 表单元素节点\n     * @param  {String}      arg1 - 显示信息\n     * @param  {String}      arg2 - 信息类型\n     * @return {Void}\n     */\n    _pro.__doShowMessage = (function(){\n        var _kmap = {tp:'tip',ok:'pass',er:'error'};\n        var _getVisible = function(_type1,_type2){\n            return _type1==_type2?'block':'none';\n        };\n        var _getHolder = function(_node,_type,_message){\n            var _holder = _getHolderNode.call(this,_node,_type);\n            if (!_holder&&!!_message)\n                _holder = _e._$wrapInline(_node,this.__wopt[_type]);\n            return _holder;\n        };\n        var _getHolderNode = function(_node,_type){\n            // try get node with id = xxx-tip or xxx-pass or xxx-error\n            var _holder = _e._$get(_node.name+'-'+_kmap[_type]);\n            if (!_holder)\n                _holder = _e._$getByClassName(_node.parentNode,this.__wopt[_type].nid)[0];\n            return _holder;\n        };\n        return function(_node,_message,_type){\n            _node = this._$get(_node)||_node;\n            if (!_node) return;\n            _type=='er' ? _e._$addClassName(_node,this.__invalid)\n                        : _e._$delClassName(_node,this.__invalid);\n            // set message content\n            var _holder = _getHolder.call(this,_node,_type,_message);\n            if (!!_holder&&!!_message) _holder.innerHTML = _message;\n            // show message node\n            _u._$loop(this.__wopt,\n                function(_value,_key){\n                    _e._$setStyle(\n                        _getHolderNode.call(this,_node,_key),\n                        'display',_getVisible(_type,_key)\n                    );\n                },this);\n        };\n    })();\n    /**\n     * 显示提示信息\n     * \n     * @method module:util/form/form._$$WebForm#_$showTip\n     * @param  {String|Node} arg0 - 表单元素节点或者名称\n     * @param  {String}      arg1 - 显示信息\n     * @return {Void}\n     */\n    _pro._$showTip = function(_node,_message){\n        this.__doShowMessage(\n            _node,_message||\n            this.__message[_node.name+'-tip'],'tp'\n        );\n    };\n    /**\n     * 显示验证通过信息\n     * \n     * @method module:util/form/form._$$WebForm#_$showMsgPass\n     * @param  {String|Node} arg0 - 表单元素节点或者名称\n     * @param  {String}      arg1 - 显示信息\n     * @return {Void}\n     */\n    _pro._$showMsgPass = function(_node,_message){\n        this.__doShowMessage(\n            _node,_message||\n            this.__message[_node.name+'-pass']||\n            this.__message.pass,'ok'\n        );\n    };\n    /**\n     * 显示错误信息\n     * \n     * @method module:util/form/form._$$WebForm#_$showMsgError\n     * @param  {String|Node} arg0 - 表单元素节点或者名称\n     * @param  {String}      arg1 - 显示信息\n     * @return {Void}\n     */\n    _pro._$showMsgError = function(_node,_message){\n        this.__doShowMessage(_node,_message||\n            this.__message[_node.name+'-error'],'er');\n    };\n    /**\n     * 设置表单控件值\n     * \n     * @method module:util/form/form._$$WebForm#_$setValue\n     * @param  {String} arg0 - 表单控件名称\n     * @param  {String} arg1 - 值\n     * @return {Void}\n     */\n    _pro._$setValue = (function(){\n        var _reg0 = /^(?:radio|checkbox)$/i;\n        // get value\n        var _getValue = function(_value){\n            return _value==null?'':_value;\n        };\n        // set select value\n        var _doSetSelect = function(_value,_node){\n            // for multiple select\n            if (!!_node.multiple){\n                var _map;\n                if (!_u._$isArray(_value)){\n                    _map[_value] = _value;\n                }else{\n                    _map = _u._$array2object(_value);\n                }\n                _u._$forEach(\n                    _node.options,function(_option){\n                        _option.selected = _map[_option.value]!=null;\n                    }\n                );\n            }else{\n                _node.value = _getValue(_value);\n            }\n        };\n        // set node value\n        var _doSetValue = function(_value,_node){\n            if (_reg0.test(_node.type||'')){\n                // radio/checkbox\n                _node.checked = _value==_node.value;\n            }else if(_node.tagName=='SELECT'){\n                // for select node\n                _doSetSelect(_value,_node);\n            }else{\n                // other\n                _node.value = _getValue(_value);\n            }\n        };\n        return function(_name,_value){\n            var _node = this._$get(_name);\n            if (!_node) return;\n            if(_node.tagName=='SELECT'||!_node.length){\n                // for node\n                _doSetValue(_value,_node);\n            }else{\n                // for node list\n                _u._$forEach(\n                    _node,\n                    _doSetValue._$bind(null,_value)\n                );\n            }\n        };\n    })();\n    /**\n     * 取指定名称的表单控件对象\n     * \n     * @method module:util/form/form._$$WebForm#_$get\n     * @param  {String} arg0 - 控件名称\n     * @return {Node}          表单控件对象\n     */\n    _pro._$get = function(_name){\n        return this.__form.elements[_name];\n    };\n    /**\n     * 取当前表单节点\n     * \n     * @method module:util/form/form._$$WebForm#_$form\n     * @return {Node} 当前封装的表单节点\n     */\n    _pro._$form = function(){\n        return this.__form;\n    };\n    /**\n     * 取表单数据\n     * \n     * @method module:util/form/form._$$WebForm#_$data\n     * @return {Object} 数据集合\n     */\n    _pro._$data = (function(){\n        var _reg0 = /^radio|checkbox$/i,\n            _reg1 = /^number|date$/;\n        var _doDumpValue = function(_node){\n            if (_node.tagName=='SELECT'&&!!_node.multiple){\n                var _ret = [];\n                _u._$forEach(\n                    _node.options,function(_option){\n                        if (_option.selected){\n                            _ret.push(_option.value);\n                        }\n                    }\n                );\n                return _ret.length>0?_ret:'';\n            }\n            return _node.value;\n        };\n        var _doParseValue = function(_map,_node){\n            var _name = _node.name,\n                _value = _doDumpValue(_node),\n                _info = _map[_name],\n                _type = this.__dataset(_node,'type'),\n                _time = _e._$dataset(_node,'time');\n            // parse value\n            if (_reg1.test(_type)){\n                if (_u._$isArray(_value)){\n                    _u._$forEach(\n                        _value,function(v,i,l){\n                            l[i] = this.__number(\n                                v,_type,_time\n                            );\n                        },this\n                    );\n                }else{\n                    _value = this.__number(\n                        _value,_type,_time\n                    );\n                }\n            }\n            // checkbox and radio\n            if (_reg0.test(_node.type)&&!_node.checked){\n                _value = this.__dataset(_node,'value');\n                if (!_value) return;\n            }\n            // if name exist\n            if (!!_info){\n                if (!_u._$isArray(_info)){\n                    _info = [_info];\n                    _map[_name] = _info;\n                }\n                _info.push(_value);\n            }else{\n                _map[_name] = _value;\n            }\n        };\n        return function(){\n            var _result = {};\n            _u._$forEach(\n                this.__form.elements,\n                function(_node){\n                    if (this.__isValueElement(_node)){\n                        _doParseValue.call(this,_result,_node);\n                    }\n                },this);\n            return _result;\n        };\n    })();\n    /**\n     * 重置表单\n     * \n     * @method module:util/form/form._$$WebForm#_$reset\n     * @return {Void}\n     */\n    _pro._$reset = (function(){\n        var _doShowTip = function(_node){\n            if (this.__isValidElement(_node)){\n                this._$showTip(_node);\n            }\n        };\n        return function(){\n            this.__form.reset();\n            _u._$forEach(\n                this.__form.elements,\n                _doShowTip,this\n            );\n        };\n    })();\n    /**\n     * 提交表单\n     * \n     * @method module:util/form/form._$$WebForm#_$submit\n     * @return {Void}\n     */\n    _pro._$submit = function(){\n        this.__form.submit();\n    };\n    /**\n     * 刷新验证信息\n     * \n     * @method module:util/form/form._$$WebForm#_$refresh\n     * @return {Void}\n     */\n    _pro._$refresh = (function(){\n        var _doPrepareElement = function(_node){\n            if (this.__isValidElement(_node)){\n                this.__doPrepareElement(_node);\n            }\n        };\n        return function(){\n            // id:{func:[],data:{}}\n            // func  - validate function list\n            // data  - validate information\n            this.__vinfo = {};\n            _u._$forEach(\n                this.__form.elements,\n                _doPrepareElement,this\n            );\n        };\n    })();\n    /**\n     * 验证表单或者表单控件\n     * \n     * @method module:util/form/form._$$WebForm#_$checkValidity\n     * @param  {String|Node} arg0 - 表单控件，没有输入表示验证整个表单\n     * @return {Boolean}            表单是否通过验证\n     */\n    _pro._$checkValidity = function(_node){\n        _node = this._$get(_node)||_node;\n        // check single form element\n        if (!!_node){\n            return this.__doCheckValidity(_node);\n        }\n        // check all form elements\n        var _result = !0;\n        _u._$forEach(\n            this.__form.elements,\n            function(_node){\n                var _pass = this._$checkValidity(_node);\n                _result = _result&&_pass;\n            },this);\n        return _result;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/form/test/form.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>form测试页</title>\n \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style>\n\t\t\tbody{text-align:left;}\t\t\n\t\t\t#form input{width:300px;}\n\t\t\t.js-placeholder{color:#aaa;font-style:italic;}\n\t\t\tlabel.js-placeholder{height:20px;line-height:20px;left:0;top:0;}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit form test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n\t\t<form id=\"form\" data-focus-mode=\"1\">\n\t\t\t<p><label>用户名：</label>\n\t\t\t<input data-auto-focus=\"false\" data-required=\"true\" \n\t\t\tdata-message=\"必须输入xxx！\" data-tip=\"用户名最长20个中文！\"\n\t\t\tvalue=\"cheng-lin\" type=\"text\" name=\"username\" maxlength=\"20\" />\n\t\t\t<span id=\"username-tip\">用户名最长20个中文！</span>\n\t\t\t</p><p><label>密码：</label>\n\t\t\t<input data-auto-focus=\"false\" data-required=\"true\" \n\t\t\tdata-message=\"密码不符合规范！\" data-tip=\"密码长度6-14！\"\n\t\t\tvalue=\"123456\" type=\"password\" name=\"password\" minlength=\"6\" maxlength=\"14\" />\n\t\t\t</p><p><label>手机：</label>\n\t\t\t<input data-auto-focus=\"false\" data-required=\"true\" \n\t\t\tdata-message=\"请输入正确的手机号！\" data-tip=\"请输入手机号！\" data-pattern=\"^+[\\\\d]+$\"\n\t\t\tvalue=\"+86013456934078\" type=\"text\" name=\"phone\" minlength=\"11\" maxlength=\"17\" />\n\t\t\t</p><p><label>地址：</label>\n\t\t\t<input data-auto-focus=\"false\" data-required=\"true\" \n\t\t\tdata-message=\"请输入正确的地址！\" data-tip=\"请输入地址！\"\n\t\t\tvalue=\"网商路599号网易杭州网络有限公司B6F-A115\" type=\"text\" name=\"address\" minlength=\"6\" maxlength=\"200\" />\n\t\t\t</p><p><label>email：</label>\n\t\t\t<input data-auto-focus=\"false\" data-required=\"true\" \n\t\t\tdata-message=\"请输入正确的邮箱地址！\" data-tip=\"请输入邮箱！\"\n\t\t\tvalue=\"cheng-lin@corp.netease.com\" type=\"text\" data-type=\"email\" name=\"email\" minlength=\"6\" maxlength=\"50\" />\n\t\t\t</p><p><label>email2：</label>\n\t\t\t<input data-auto-focus=\"false\" data-required=\"true\" \n\t\t\tdata-message=\"请输入正确的邮箱地址！\" data-tip=\"请输入邮箱！\"\n\t\t\tvalue=\"cheng-lin@corp.netease.com\" type=\"text\" data-type=\"email\" name=\"emailt\" data-min-length=\"6\" data-max-length=\"50\" />\n\t\t\t</p><p><label>真实姓名：</label>\n\t\t\t<input data-auto-focus=\"false\" data-required=\"true\" \n\t\t\tdata-message=\"请输入正确的姓名(2到12字)！\" data-tip=\"请输入真实姓名(2到12字)！\"\n\t\t\tvalue=\"程霖\" type=\"text\" name=\"realname\" minlength=\"2\" maxlength=\"12\" />\n\t\t\t</p><p><label>日期：</label>\n\t\t\t<input data-auto-focus=\"false\" data-required=\"true\" \n\t\t\tdata-message=\"请输入正确的日期！\" data-tip=\"请输入日期,格式(99-09-31，99/09/31)！\" type=\"text\"\n\t\t\tdata-type=\"date\" name=\"date\" />\n\t\t\t</p><p><label>简介：</label>\n\t\t\t<textarea placeholder=\"(10到100字)\" data-auto-focus=\"false\" data-required=\"true\" \n\t\t\tdata-message=\"请输入正确的简介(10到100字)！\" name=\"introduce\" minlength=\"10\" maxlength=\"100\"></textarea>\n\t\t\t</p>\n\t\t\t<div id=\"check\">检查规则</div>\n\t\t</form>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./form.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/util/form/test/form.test.js",
    "content": "var f = function(){\n\t//定义测试模块\n\tmodule(\"form\");\n\tvar p = NEJ.P('nej.ut'),\n\t\tv = NEJ.P('nej.v'),\n\t\te = NEJ.P('nej.e');\n\t\n\t//开始单元测试\n\ttest('验证完整的form表单,', function() {\n\t\tvar _check = e._$get('check');\n\t\tvar _form = p._$$WebForm._$allocate({\n\t\t\tform:'form',\n\t\t\tmessage:{\n\t\t\t\t'email100':'两次email地址不一致',\n\t\t\t\t'emailt100':'两次email地址不一致',\n\t\t\t\t'email2-5':'email地址太长'\n\t\t\t},\n\t\t\toncheck:function(_event){\n//\t\t\t\tif(_event.target.name==\"emailt\"){\n//\t\t\t\t   _event.value = 100;\n//\t\t\t\t}\n\t\t\t},\n            oninvalid:function(_event){\n//\t\t\t\t_event.value = '<span>'+_event.code+'</span>'\n//              if (_event.target.name=='address'&&_event.code==-1){\n//                   _event.value = '必须输入密码！';\n//              }\n            },\n            onvalid:function(_event){\n//\t\t\t\tif (_event.target.name == 'emailt') {\n//\t\t\t\t}\n            }\n\t\t});\n\t\tv._$addEvent(_check,'click',function(){\n\t\t\t_form._$checkValidity();\n\t\t});\n\t\tsetTimeout(function(){\n\t\t\tv._$dispatchEvent(_check,'click');\n\t\t},2000);\n\t\tok(true,'没有异常中断');\n\t});\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n\tdefine('{pro}form.test.js',\n\t['{lib}util/form/form.js'],f);\n});\n"
  },
  {
    "path": "src/util/gestrue/drag.js",
    "content": "/*\n * ------------------------------------------\n * 点击手势封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/gestrue/drag */\nNEJ.define([\n    'base/klass',\n    './gestrue.js'\n],function(_k,_t,_p,_o,_f,_r,_pro){\n    /**\n     * \n     * tap taphold dbltap\n     * \n     * @class    module:util/gestrue/drag._$$GestrueDrag\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object}      config  - 配置参数\n     * \n     * \n     */\n    _p._$$GestrueDrag = _k._$klass();\n    _pro = _p._$$GestrueDrag._$extend(_t._$$Gestrue);\n    /**\n     * 控件初始化\n     * \n     * @protected\n     * @method module:util/gestrue/drag._$$GestrueDrag#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        \n    };\n    /**\n     * 开始触摸\n     * \n     * @protected\n     * @method module:util/gestrue/drag._$$GestrueDrag#__onTouchStart\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchStart = function(_event){\n        \n    };\n    /**\n     * 触摸进行中\n     * \n     * @protected\n     * @method module:util/gestrue/drag._$$GestrueDrag#__onTouchMove\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchMove = function(_event){\n        \n    };\n    /**\n     * 触摸结束\n     * \n     * @protected\n     * @method module:util/gestrue/drag._$$GestrueDrag#__onTouchEnd\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchEnd = function(_event){\n        \n    };\n    \n    \n});\n"
  },
  {
    "path": "src/util/gestrue/gestrue.js",
    "content": "/*\n * ------------------------------------------\n * 手势基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/gestrue/gestrue */\nNEJ.define([\n    'base/klass',\n    'base/event',\n    'util/event'\n],function(_k,_v,_t,_p,_o,_f,_r,_pro){\n    /**\n     * \n     * \n     * \n     * @class    module:util/gestrue/gestrue._$$Gestrue\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object}      config  - 配置参数\n     * \n     * \n     */\n    _p._$$Gestrue = _k._$klass();\n    _pro = _p._$$Gestrue._$extend(_t._$$EventTarget);\n    /**\n     * 控件初始化\n     * \n     * @protected\n     * @method module:util/gestrue/gestrue._$$Gestrue#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__touches = {};\n        this.__doInitDomEvent([[\n            document,'touchstart',\n            this.__onTouchStart._$bind(this)\n        ],[\n            document,'touchmove',\n            this.__onTouchMove._$bind(this)\n        ],[\n            document,'touchend',\n            this.__onTouchEnd._$bind(this)\n        ],[\n            document,'touchcancel',\n            this.__onTouchEnd._$bind(this)\n        ]]);\n    };\n    /**\n     * 开始触摸\n     * \n     * @protected\n     * @method module:util/gestrue/gestrue._$$Gestrue#__onTouchStart\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchStart = function(_event){\n        \n    };\n    /**\n     * 触摸进行中\n     * \n     * @protected\n     * @method module:util/gestrue/gestrue._$$Gestrue#__onTouchMove\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchMove = function(_event){\n        \n    };\n    /**\n     * 触摸结束\n     * \n     * @protected\n     * @method module:util/gestrue/gestrue._$$Gestrue#__onTouchEnd\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchEnd = function(_event){\n        \n    };\n    /**\n     * 触发手势事件\n     * \n     * @method module:util/gestrue/gestrue._$$Gestrue#_$fire\n     * @param  {String}   arg0 - 事件类型\n     * @param  {Variable} arg1 - 详细参数\n     * @return {Void}\n     */\n    _pro._$fire = function(_type,_detail){\n        \n    };\n    \n    \n    \n    return _p._$$Gestrue._$allocate();\n});\n"
  },
  {
    "path": "src/util/gestrue/pinch.js",
    "content": "/*\n * ------------------------------------------\n * 点击手势封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/gestrue/pinch */\nNEJ.define([\n    'base/klass',\n    './gestrue.js'\n],function(_k,_t,_p,_o,_f,_r,_pro){\n    /**\n     * \n     * tap taphold dbltap\n     * \n     * @class    module:util/gestrue/pinch._$$GestruePinch\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object}      config  - 配置参数\n     * \n     * \n     */\n    _p._$$GestruePinch = _k._$klass();\n    _pro = _p._$$GestruePinch._$extend(_t._$$Gestrue);\n    /**\n     * 控件初始化\n     * \n     * @protected\n     * @method module:util/gestrue/pinch._$$GestruePinch#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        \n    };\n    /**\n     * 开始触摸\n     * \n     * @protected\n     * @method module:util/gestrue/pinch._$$GestruePinch#__onTouchStart\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchStart = function(_event){\n        \n    };\n    /**\n     * 触摸进行中\n     * \n     * @protected\n     * @method module:util/gestrue/pinch._$$GestruePinch#__onTouchMove\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchMove = function(_event){\n        \n    };\n    /**\n     * 触摸结束\n     * \n     * @protected\n     * @method module:util/gestrue/pinch._$$GestruePinch#__onTouchEnd\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchEnd = function(_event){\n        \n    };\n    \n    \n});\n"
  },
  {
    "path": "src/util/gestrue/rotate.js",
    "content": "/*\n * ------------------------------------------\n * 点击手势封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/gestrue/rotate */\nNEJ.define([\n    'base/klass',\n    './gestrue.js'\n],function(_k,_t,_p,_o,_f,_r,_pro){\n    /**\n     * \n     * tap taphold dbltap\n     * \n     * @class    module:util/gestrue/rotate._$$GestrueRotate\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object}      config  - 配置参数\n     * \n     * \n     */\n    _p._$$GestrueRotate = _k._$klass();\n    _pro = _p._$$GestrueRotate._$extend(_t._$$Gestrue);\n    /**\n     * 控件初始化\n     * \n     * @protected\n     * @method module:util/gestrue/rotate._$$GestrueRotate#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        \n    };\n    /**\n     * 开始触摸\n     * \n     * @protected\n     * @method module:util/gestrue/rotate._$$GestrueRotate#__onTouchStart\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchStart = function(_event){\n        \n    };\n    /**\n     * 触摸进行中\n     * \n     * @protected\n     * @method module:util/gestrue/rotate._$$GestrueRotate#__onTouchMove\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchMove = function(_event){\n        \n    };\n    /**\n     * 触摸结束\n     * \n     * @protected\n     * @method module:util/gestrue/rotate._$$GestrueRotate#__onTouchEnd\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchEnd = function(_event){\n        \n    };\n    \n    \n});\n"
  },
  {
    "path": "src/util/gestrue/swipe.js",
    "content": "/*\n * ------------------------------------------\n * 点击手势封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/gestrue/swipe */\nNEJ.define([\n    'base/klass',\n    './gestrue.js'\n],function(_k,_t,_p,_o,_f,_r,_pro){\n    /**\n     * \n     * \n     * \n     * @class    module:util/gestrue/swipe._$$GestrueSwipe\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object}      config  - 配置参数\n     * \n     * \n     */\n    _p._$$GestrueSwipe = _k._$klass();\n    _pro = _p._$$GestrueSwipe._$extend(_t._$$Gestrue);\n    /**\n     * 控件初始化\n     * \n     * @protected\n     * @method module:util/gestrue/swipe._$$GestrueSwipe#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        \n    };\n    /**\n     * 开始触摸\n     * \n     * @protected\n     * @method module:util/gestrue/swipe._$$GestrueSwipe#__onTouchStart\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchStart = function(_event){\n        \n    };\n    /**\n     * 触摸进行中\n     * \n     * @protected\n     * @method module:util/gestrue/swipe._$$GestrueSwipe#__onTouchMove\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchMove = function(_event){\n        \n    };\n    /**\n     * 触摸结束\n     * \n     * @protected\n     * @method module:util/gestrue/swipe._$$GestrueSwipe#__onTouchEnd\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchEnd = function(_event){\n        \n    };\n    \n    \n});\n"
  },
  {
    "path": "src/util/gestrue/tap.js",
    "content": "/*\n * ------------------------------------------\n * 点击手势封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/gestrue/tap */\nNEJ.define([\n    'base/klass',\n    './gestrue.js'\n],function(_k,_t,_p,_o,_f,_r,_pro){\n    /**\n     * \n     * tap taphold dbltap\n     * \n     * @class    module:util/gestrue/tap._$$GestrueTap\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object}      config  - 配置参数\n     * \n     * \n     */\n    _p._$$GestrueTap = _k._$klass();\n    _pro = _p._$$GestrueTap._$extend(_t._$$Gestrue);\n    /**\n     * 控件初始化\n     * \n     * @protected\n     * @method module:util/gestrue/tap._$$GestrueTap#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        \n    };\n    /**\n     * 开始触摸\n     * \n     * @protected\n     * @method module:util/gestrue/tap._$$GestrueTap#__onTouchStart\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchStart = function(_event){\n        \n    };\n    /**\n     * 触摸进行中\n     * \n     * @protected\n     * @method module:util/gestrue/tap._$$GestrueTap#__onTouchMove\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchMove = function(_event){\n        \n    };\n    /**\n     * 触摸结束\n     * \n     * @protected\n     * @method module:util/gestrue/tap._$$GestrueTap#__onTouchEnd\n     * @param  {Object} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTouchEnd = function(_event){\n        \n    };\n    \n    \n});\n"
  },
  {
    "path": "src/util/helper/select.js",
    "content": "/*\n * ------------------------------------------\n * 选择助手控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/helper/select */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'util/event'\n],function(NEJ,_k,_e,_v,_t,_p,_o,_f,_r,_pro){\n    /**\n     * 选择助手控件\n     * \n     * 结构举例\n     * ```html\n     *  <!-- 搜索祖先节点，找到设置了tabindex大于1000的节点来响应键盘上下事件，找不到为document -->\n     *  <div id=\"xxx\" tabindex=\"1005\">\n     *    <p>aaaaaaaaaaaaaa</p>\n     *    <p>bbbbbbbbbbbbbb</p>\n     *    <p>cccccccccccccc</p>\n     *    <p>dddddddddddddd</p>\n     *    <p>eeeeeeeeeeeeee</p>\n     *    <p>ffffffffffffff</p>\n     *    <p>gggggggggggggg</p>\n     *  </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/helper/select'\n     * ],function(_t){\n     *     var _helper = _t._$$SelectHelper._$allocate({\n     *          parent:'xxx',\n     *          loopable:!0,\n     *          onchange:function(_event){\n     *              // _event.last\n     *              // _event.target\n     *              console.log('selection change -> '+_event.target.innerText);\n     *          },\n     *          onselect:function(_event){\n     *              // _event.target\n     *              console.log('select -> '+_event.target.innerText);\n     *          }\n     *     });\n     * });\n     * ```\n     * @class    module:util/helper/select._$$SelectHelper\n     * @extends  module:util/event._$$EventTarget\n     * @param    {Object}      config   - 可选配置参数\n     * @property {String|Node} parent   - 容器节点，从该容器开始往上遍历找到设置了tabindex大于1000的节点来响应键盘上下事件，找不到为document\n     * @property {String}      clazz    - 用于标识可选择的节点，不传则为body下的子节点\n     * @property {String}      selected - 选中节点样式标识，默认为js-selected\n     * @property {String}      hover    - 鼠标移入样式标识，默认同selected，如果hover样式和selected不一样，确保selected样式优先级高于hover\n     * @property {Boolean}     loopable - 是否允许循环选择\n     */\n    /**\n     * 选择项变化触发事件\n     * @event    module:util/helper/select._$$SelectHelper#onchange\n     * @param    {Object} event  - 选择信息\n     * @property {Node}   target - 当前选中项\n     * @property {Node}   last   - 上次选中项\n     */\n    /**\n     * 选中某项触发事件，用户敲回车或者鼠标单击选项时触发此事件\n     * @event    module:util/helper/select._$$SelectHelper#onselect\n     * @param    {Object} event  - 选择信息\n     * @property {Node}   target - 当前选中项\n     */\n    _p._$$SelectHelper = _k._$klass();\n    _pro = _p._$$SelectHelper._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/helper/select._$$SelectHelper#__reset\n     * @param  {Object} arg0 - 配置信息\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__loop = !!_options.loopable;\n        this.__parent = _e._$get(_options.parent);\n        this.__selected = _options.selected||'js-selected';\n        this.__hovered = _options.hover||this.__selected;\n        this.__nopt = {};\n        if (!!_options.clazz){\n            this.__nopt.filter =\n                _e._$hasClassName.\n                    _$bind2(_e,_options.clazz);\n            this.__clazz = _options.clazz;\n        }\n        // init event\n        this.__kbody = this.__getKeyBoardParent(\n            this.__parent\n        );\n        this.__doInitDomEvent([[\n            this.__kbody,'keydown',\n            this.__doCheckKBAction._$bind(this),!0\n        ],[\n            this.__kbody,'enter',\n            this.__doCheckKBEnter._$bind(this)\n        ],[\n            this.__parent,'click',\n            this.__onCheckClick._$bind(this)\n        ],[\n            this.__parent,'mouseover',\n            this.__onCheckHover._$bind(this)\n        ],[\n            this.__parent,'mouseleave',\n            this.__onCheckLeave._$bind(this)\n        ]]);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/helper/select._$$SelectHelper#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__selected;\n        delete this.__hovered;\n        delete this.__parent;\n        delete this.__kbody;\n        delete this.__clazz;\n        delete this.__nopt;\n        delete this.__loop;\n    };\n    /**\n     * 判断节点是否选项节点\n     *\n     * @protected\n     * @method module:util/helper/select._$$SelectHelper#__isItemElement\n     * @param  {Node} ar0 - 节点\n     * @return {Boolean}    是否选项\n     */\n    _pro.__isItemElement = function(_element){\n        if (!!this.__clazz){\n            return _e._$hasClassName(\n                _element,this.__clazz\n            );\n        }\n        return _element.parentNode==this.__parent;\n    };\n    /**\n     * 取键盘检测节点\n     *\n     * @protected\n     * @method module:util/helper/select._$$SelectHelper#__getKeyBoardParent\n     * @return {Node} 节点\n     */\n    _pro.__getKeyBoardParent = (function(){\n        var _max = 1000;\n        return function(_element){\n            while(!!_element&&(parseInt(_element.tabIndex)||0)<=_max){\n                _element = _element.parentNode;\n            }\n            return _element||document;\n        };\n    })();\n    /**\n     * 根据样式取项节点\n     *\n     * @protected\n     * @method module:util/helper/select._$$SelectHelper#__getItemElement\n     * @return {Node} 节点\n     */\n    _pro.__getItemElement = function(_class){\n        var _list = _e._$getByClassName(\n            this.__parent,_class\n        );\n        return !_list?null:_list[0];\n    };\n    /**\n     * 同步选中状态\n     *\n     * @protected\n     * @method module:util/helper/select._$$SelectHelper#__doSyncSelection\n     * @return {Void}\n     */\n    _pro.__doSyncSelection = function(_event,_class){\n        // update state\n        _e._$delClassName(_event.last,_class);\n        _e._$addClassName(_event.target,_class);\n        // trigger onselectionchange\n        if (_class==this.__selected&&\n            _event.last!=_event.target){\n            this.__doScrollToView(_event.target);\n            this._$dispatchEvent(\n                'onchange',_event\n            );\n        }\n    };\n    /**\n     * 节点滚动至可视区域\n     *\n     * @protected\n     * @method module:util/helper/select._$$SelectHelper#__doScrollToView\n     * @return {Void}\n     */\n    _pro.__doScrollToView = function(_element){\n        var _parent = _e._$getScrollViewPort(_element),\n            _offset = _e._$offset(_element,_parent);\n        // item out of top\n        if (_offset.y-_parent.scrollTop<0){\n            _parent.scrollTop = _offset.y;\n            return;\n        }\n        // item out of bottom\n        var _delta = _offset.y+\n            _element.offsetHeight-_parent.clientHeight;\n        if (_delta>_parent.scrollTop){\n            _parent.scrollTop = _delta;\n        }\n    };\n    /**\n     * 解析选择状态\n     *\n     * @protected\n     * @method module:util/helper/select._$$SelectHelper#__doParseSelection\n     * @return {Object} 状态信息\n     */\n    _pro.__doParseSelection = function(_event,_class){\n        var _element = _v._$getElement(\n            _event,this.__isItemElement._$bind(this)\n        );\n        return !_element?null:{\n            last:this.__getItemElement(_class),\n            target:_element\n        };\n    };\n    /**\n     * 触发键盘选择实践\n     *\n     * @protected\n     * @method module:util/helper/select._$$SelectHelper#__doCheckKBAction\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__doCheckKBAction = function(_event){\n        var _code = _event.keyCode;\n        // only for up and down\n        if (_code!=38&&_code!=40) return;\n        _v._$stop(_event);\n        var _eopt = {\n            last:this._$getSelectedNode()\n        };\n        // calculate last and target\n        this.__nopt.backward = _code==38;\n        var _list = !this.__clazz\n                  ? _e._$getChildren(this.__parent)\n                  : _e._$getByClassName(this.__parent,this.__clazz),\n            _next = this.__nopt.backward\n                  ? _list[_list.length-1]\n                  : _list[0];\n        if (!_eopt.last){\n            _eopt.target = this.__getItemElement(\n                this.__hovered\n            )||_next;\n        }else{\n            _eopt.target = _e._$getSibling(\n                _eopt.last,this.__nopt\n            );\n        }\n        // check loop selection\n        if (!_eopt.target){\n            if (!this.__loop||_list.length<=1){\n                return;\n            }\n            _eopt.target = _next;\n        }\n        this.__doSyncSelection(_eopt,this.__selected);\n    };\n    /**\n     * 回车事件\n     *\n     * @protected\n     * @method module:util/helper/select._$$SelectHelper#__doCheckKBEnter\n     * @return {Void}\n     */\n    _pro.__doCheckKBEnter = function(_event){\n        _v._$stop(_event);\n        this._$dispatchEvent('onselect',{\n            enter:!0,\n            target:this._$getSelectedNode()\n        });\n    };\n    /**\n     * 点击事件\n     *\n     * @protected\n     * @method module:util/helper/select._$$SelectHelper#__onCheckClick\n     * @return {Void}\n     */\n    _pro.__onCheckClick = function(_event){\n        _v._$stop(_event);\n        var _eopt = this.__doParseSelection(\n            _event,this.__selected\n        );\n        if (!_eopt) return;\n        this.__doSyncSelection(\n            _eopt,this.__selected\n        );\n        this._$dispatchEvent('onselect',{\n            target:_eopt.target\n        });\n    };\n    /**\n     * 鼠标移入事件\n     *\n     * @protected\n     * @method module:util/helper/select._$$SelectHelper#__onCheckHover\n     * @return {Void}\n     */\n    _pro.__onCheckHover = function(_event){\n        var _eopt = this.__doParseSelection(\n            _event,this.__hovered\n        );\n        if (!_eopt) return;\n        this.__doSyncSelection(\n            _eopt,this.__hovered\n        );\n        if (!!this.__kbody.focus){\n            this.__kbody.focus();\n        }\n    };\n    /**\n     * 鼠标移出事件\n     *\n     * @protected\n     * @method module:util/helper/select._$$SelectHelper#__onCheckLeave\n     * @return {Void}\n     */\n    _pro.__onCheckLeave = function(_event){\n        if (this.__hovered==this.__selected){\n            return;\n        }\n        _e._$delClassName(\n            this.__getItemElement(this.__hovered),\n            this.__hovered\n        );\n    };\n    /**\n     * 取当前选中的节点\n     *\n     * @method module:util/helper/select._$$SelectHelper#_$getSelectedNode\n     * @return {Node} 当前选中节点\n     */\n    _pro._$getSelectedNode = function(){\n        return this.__getItemElement(this.__selected);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/highlight/test/highlight.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>highlight测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n        <style type=\"text/css\">\n        .red{color:red;}\n        </style>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit xdr test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <div id=\"abc\" data-highlight=\"js-highlight\">aaaaa</div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./highlight.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/highlight/test/highlight.test.js",
    "content": "NEJ.define(['util/highlight/touch'],function(_t){\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v');\n    test('highlight',function(){\n        expect(0);\n        _t._$highlight('abc','red');\n    });\n});"
  },
  {
    "path": "src/util/highlight/touch.js",
    "content": "/*\n * ------------------------------------------\n * 高亮接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/highlight/touch */\nNEJ.define([\n    'base/global',\n    'base/event',\n    'base/element',\n    'base/chain'\n],function(NEJ,_v,_e,_x,_p,_o,_f,_r){\n    /**\n     * 节点鼠标或手势按下高亮行为，移动触摸反馈\n     *\n     * 样式举例\n     * ```css\n     *    .page .element.js-highlight{background:#f00;}\n     * ```\n     *\n     * 结构举例\n     * ```html\n     *    <!-- 使用data-highlight指定highlight效果的样式名称 -->\n     *    <div id=\"abc\" data-highlight=\"js-highlight\">aaaaa</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'util/highlight/touch'\n     *   ],function(_e){\n     *       // 如果highlight效果的样式名已经通过data-hover指定\n     *       _e._$highlight('abc');\n     *       // 如果highlight效果的样式名没有通过data-hover指定\n     *       _e._$highlight('abc','js-highlight');\n     *   });\n     * ```\n     *\n     * @method module:util/highlight/touch._$highlight\n     * @param  {String|Node} arg0 - 节点\n     * @param  {String}      arg1 - 样式，默认为js-highlight\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$highlight\n     * @see module:util/highlight/touch._$highlight\n     */\n    _p._$highlight = (function(){\n        var _cache = {},\n            _distance = 2;\n        // touch start event\n        var _doTouchStart = function(_id,_clazz,_event){\n            _cache[_id] = _v._$page(_event);\n            _e._$addClassName(_id,_clazz);\n        };\n        // touchmove event\n        var _doTouchMove = function(_id,_clazz,_event){\n            var _point = _cache[_id];\n            if (_point===-1) return;\n            var _xy = _v._$page(_event),\n                _dx = Math.abs(_xy.x-_point.x),\n                _dy = Math.abs(_xy.y-_point.y);\n            if (_dx>_distance||_dy>_distance){\n                _doTouchEnd(_id,_clazz);\n            }\n        };\n        // touchend/touchcancel event\n        var _doTouchEnd = function(_id,_clazz){\n            if (_cache[_id]!==-1){\n                _cache[_id] = -1;\n                _e._$delClassName(_id,_clazz);\n            }\n        };\n        return function(_element,_clazz){\n            var _id = _e._$id(_element);\n            if (!_id||_cache[_id]!=null){\n                return;\n            }\n            // lock element\n            _cache[_id] = -1;\n            _clazz = _clazz||\n                     _e._$dataset(_id,'highlight')||\n                     'js-highlight';\n            // add event\n            _v._$addEvent(\n                _id,'touchstart',\n                _doTouchStart._$bind(null,_id,_clazz)\n            );\n            _v._$addEvent(\n                document,'touchmove',\n                _doTouchMove._$bind(null,_id,_clazz)\n            );\n            _v._$addEvent(\n                document,'touchend touchcancel',\n                _doTouchEnd._$bind(null,_id,_clazz)\n            );\n        };\n    })();\n    // for chainable method\n    _x._$merge(_p);\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.e'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/history/history.js",
    "content": "/*\n * ------------------------------------------\n * HTML5 - History API封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/util',\n    'base/event',\n    'base/platform',\n    'util/event/event',\n    'util/timer/animation',\n    '{platform}history.js'\n],function(_u,_v,_m,_t0,_t1,_h,_p,_o,_f,_r){\n    var _reg1 = /^[#?]+/,\n        _reg2 = /#(.*?)$/,\n        _ctxt = this;\n    /*\n     * 判断是否需要做Hack处理\n     * @return {Boolean} 是否需要做Hack处理\n     */\n    var _isHack = function(){\n        return !history.pushState||_m._$IS.android||!history.auto;\n    };\n    /*\n     * 设置地址\n     * @param  {String}  页面地址\n     * @param  {Boolean} 是否不保存历史\n     * @return {Void}\n     */\n    var _setLocation = function(_url,_replaced){\n        var _name = !_replaced?'pushState':'replaceState';\n        _ctxt.history[_name](null,document.title,_url);\n    };\n    /*\n     * 取位置信息\n     * @return {Object} 位置信息\n     */\n    var _getLocation = function(){\n        return location.parse(_ctxt.location.href);\n    };\n    // extend api\n    _setLocation = \n    _setLocation._$aop(function(_event){\n        if (!_isHack()) return;\n        _event.stopped = !0;\n        var _args = _event.args;\n        // not encodeURIComponent\n        _url = _args[0].replace(_reg1,'');\n        !_args[1] ? _ctxt.location.hash = _url\n                  : _ctxt.location.replace('#'+_url);\n    });\n    _getLocation = \n    _getLocation._$aop(function(_event){\n        if (!_isHack()) return;\n        _event.stopped = !0;\n        // fix ie6 location.hash error for #/m/a?a=aaa\n        var _hash = _reg2.test(_ctxt.location.href)?RegExp.$1:'';\n        // not decodeURIComponent\n        _event.value = location.parse(_hash.replace(_reg1,''));\n    });\n    /**\n     * 重定向路径\n     * \n     * @method external:location.redirect\n     * @param  {String}  arg0 - 路径\n     * @param  {Boolean} arg1 - 是否替换原来的历史\n     * @return {Void}\n     */\n    location.redirect = function(_url,_replaced){\n        _setLocation(_url,_replaced);\n    };\n    /**\n     * 启动地址检测\n     * \n     * @method external:location.active\n     * @return {Void}\n     */\n    location.active = (function(){\n        var _timer,_url,_location,_locked,_done;\n        // parse location change\n        var _onLocationChange = function(_href){\n            // locked from history back\n            if (!!_locked){\n                _locked = !1;\n                return;\n            }\n            var _event = {\n                oldValue:_location,\n                newValue:_getLocation()\n            };\n            // check ignore beforeurlchange event fire\n            if (!!location.ignored){\n                location.ignored = !1;\n            }else{\n                _v._$dispatchEvent(\n                    location,'beforeurlchange',_event\n                );\n                if (_event.stopped){\n                    if (!!_location){\n                        _locked = !0;\n                        _setLocation(_location.href,!0);\n                    }\n                    return;\n                };\n            }\n            // fire urlchange\n            _url = _ctxt.location.href;\n            _location = _event.newValue;\n            _v._$dispatchEvent(\n                location,'urlchange',_location\n            );\n            _h.__pushHistory(_location.href);\n        };\n        // check location\n        var _doCheckLocation = function(){\n            if (_url!=_ctxt.location.href) _onLocationChange();\n            _timer = _t1.requestAnimationFrame(_doCheckLocation);\n        };\n        // check use hashchange event on window\n        var _useHashChange = function(){\n            var _knl = _m._$KERNEL;\n                 _ie7 = _knl.engine=='trident'&&_knl.release<='3.0';\n            return _isHack()&&('onhashchange' in window)&&!_ie7;\n        };\n        return function(_context){\n            // lock active\n            if (!!_done){\n                return;\n            }\n            _done = !0;\n            // do init\n            _ctxt = _context||window;\n            // ignore onhashchange on ie7\n            if (_useHashChange()){\n                _v._$addEvent(\n                    _ctxt,'hashchange',\n                    _onLocationChange\n                );\n                _onLocationChange();\n            }else if(!_timer){\n                _timer = _t1.requestAnimationFrame(_doCheckLocation);\n                _doCheckLocation();\n            }\n        };\n    })();\n    /**\n     * 地址信息对象\n     * \n     * @typedef  {Object} external:location~LocationModel\n     * @property {String} path  - 路径信息，不带查询参数\n     * @property {String} href  - 完整路径，带查询参数\n     * @property {Object} query - 查询参数解析出来的对象\n     */\n    /**\n     * 解析地址信息\n     * \n     * @method external:location.parse\n     * @param  {String} arg0 - 地址\n     * @return {external:location~LocationModel} 地址信息\n     */\n    location.parse = (function(){\n        var _reg0 = /^https?:\\/\\/.*?\\//i,\n            _reg1 = /[?#]/;\n        return function(_url){\n            // http://a.b.com/a/b/c?a=aa&b=bb#c=cc\n            var _result = {href:_url};\n            // /a/b/c?a=aa&b=bb#c=cc\n            // 0 - /a/b/c\n            // 1 - a=aa&b=bb\n            // 2 - c=cc\n            _url = (_url||'').replace(_reg0,'/').split(_reg1);\n            // for /?/a/b?a=aa&b=bb\n            var _count = 1;\n            if (_url[0]=='/'&&\n               (_url[1]||'').indexOf('/')==0)\n                _count = 2;\n            // /a/b/c or /?/a/b\n            _result.path = _url.splice(0,_count).join('?');\n            _result.query = _u._$query2object(_url.join('&'));\n            return _result;\n        };\n    })();\n    /**\n     * 判断路径和当前地址栏路径是否一致\n     * \n     * @method external:location.same\n     * @param  {String}  arg0 - 路径\n     * @return {Boolean}        是否一致\n     */\n    location.same = function(_url){\n        return _getLocation().href==_url;\n    };\n    /**\n     * 地址变化之前触发事件\n     *\n     * @event    external:location.onbeforeurlchange\n     * @param    {Object}  event   - 地址信息\n     * @property {external:location~LocationModel} oldValue - 旧地址信息\n     * @property {external:location~LocationModel} newValue - 新地址信息\n     * @property {Boolean} stopped - 是否阻止地址跳转\n     */\n    /**\n     * 地址变化触发事件\n     *\n     * @event    external:location.onurlchange\n     * @param    {external:location~LocationModel} event - 地址信息\n     */\n    _t0._$$CustomEvent._$allocate({\n        element:location,\n        event:['beforeurlchange','urlchange']\n    });\n    \n    return _p;\n});"
  },
  {
    "path": "src/util/history/history.override.js",
    "content": "// link to util/history/manager for compatible\n// use util/history/manager for new project\nNEJ.define(['./manager.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/history/manager.js",
    "content": "/*\n * ------------------------------------------\n * 重写History API封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/event',\n    './history.js'\n],function(_v,_t,_p,_o,_f,_r){\n    var _hflag = !1, // is history\n        _hpool = []; // history url list\n    /**\n     * 当前历史索引\n     * \n     * @member {Number} external:history.index\n     */\n    history.index = 0;\n    /**\n     * 历史队列长度\n     * \n     * @member {Number} external:history.size\n     */\n    history.size = _hpool.length;\n    /**\n     * 跳转到历史\n     * \n     * @method external:history.go\n     * @param  {Number} arg0 - 步长\n     * @return {Void}\n     */\n    history.go = function(_step){\n        if (history.size<2) return this;\n        var _index = history.index+_step;\n        history.index = Math.max(0,\n                        Math.min(_index,\n                        history.size-1));\n        _hflag = !0;\n        location.redirect(_hpool[history.index],!0);\n    };\n    /**\n     * 从历史记录移出一个历史\n     *\n     * @method external:history.pop\n     * @return {Void}\n     */\n    history.pop = function(){\n        _hpool.pop();\n        history.size = _hpool.length;\n        history.index = Math.min(\n            history.index,\n            history.size-1\n        );\n    };\n    /**\n     * 后退\n     * \n     * @method external:history.back\n     * @return {Void}\n     */\n    history.back = function(){\n        history.go(-1);\n    };\n    /**\n     * 前进\n     * \n     * @method external:history.forward\n     * @return {Void}\n     */\n    history.forward = function(){\n        history.go(1);\n    };\n    // listener history change\n    _v._$addEvent(\n        location,'urlchange',\n        function(_event){\n            // from history\n            if (_hflag){\n                _hflag = !1;\n                return;\n            }\n            // save history\n            var _url = _event.href,\n                _cur = _hpool[history.index];\n            if (_url!=_cur){\n                if (_cur!=null)\n                    history.index++;\n                _hpool[history.index] = _url;\n                history.size  = history.index+1;\n                // remove size -> length\n                var _count = _hpool.length-history.size;\n                if (_count>0) _hpool.splice(history.size,_count);\n            }\n        }\n    );\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/history/platform/history.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define(function(_p){\n\t/**\n     * 将Hash推入历史\n     * @param  {String} HASH值\n     * @return {Void}\n     */\n    _p.__pushHistory = function(_hash){\n        // do nothing\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/history/platform/history.patch.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    './history.js',\n    'base/element'\n],function(_h,_e,_p,_o,_f,_r){\n\t// for ie8-\n\tNEJ.patch('TR<=4.0',function(){\n\t    window.hst_lock = {};\n\t\t/**\n\t     * 将Hash推入历史\n\t     * @param  {String} HASH值\n\t     * @return {Void}\n\t     */\n\t    _h.__pushHistory = (function(){\n\t        var _timer,\n\t            _iframe,\n\t            _queue = [],\n\t            _hflag = 'cb-'+(+new Date),\n\t            _content = '<script>parent.hst_lock[\"'+_hflag+'\"] = !0;parent.location.hash = decodeURIComponent(\"#<HASH>\");</scr'+'ipt>';\n\t        var _doCheckQueue = function(){\n\t            _timer = window.clearTimeout(_timer);\n\t            if (!_queue.length) return;\n\t            var _hash = _queue.shift();\n\t            try{\n\t                var _document = _iframe.contentWindow.document;\n\t                _document.open();\n\t                _document.write('<head><title>');\n\t                _document.write(document.title);\n\t                _document.write('</title>');\n\t                _document.write(\n\t                    _content.replace(\n\t                        '#<HASH>',\n\t                        encodeURIComponent(_hash)\n\t                    )\n\t                );\n\t                _document.write('</head><body></body>');\n\t                if (location.hostname!=document.domain){\n\t                    _document.domain = document.domain;\n\t                }\n\t                _document.close();\n\t                hst_lock[_hflag] = !1;\n\t            }catch(ex){\n\t                console.log(ex.message||ex);\n\t                _queue.unshift(_hash);\n\t            }\n\t            _timer = window.setTimeout(_doCheckQueue,50);\n\t        };\n\t        return function(_hash){\n               if (!!_h[_hflag]||(!_iframe&&!_hash)){\n                   return;\n               }\n               _queue.push(_hash);\n               if (!_iframe){\n                   _iframe = _e._$createXFrame();\n               }\n               _doCheckQueue();\n            };\n\t    })();\n\t});\n    \n    return _h;\n});\n"
  },
  {
    "path": "src/util/hover/hover.js",
    "content": "/*\n * ------------------------------------------\n * HOVER接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/hover/hover */\nNEJ.define([\n    'base/global',\n    'base/element',\n    'base/chain',\n    'base/util',\n    '{platform}hover.js'\n],function(NEJ,_e,_x,_u,_h,_p,_o,_f,_r){\n    /**\n     * 节点hover行为，高版本浏览器用:hover样式处理\n     *\n     * 样式举例\n     * ```css\n     *    .page .element:hover,\n     *    .page .element.js-hover{background:#f00;}\n     * ```\n     *\n     * 结构举例\n     * ```html\n     *    <!-- 使用data-hover指定hover效果的样式名称 -->\n     *    <div id=\"abc\" data-hover=\"js-hover\">aaaaa</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'util/hover/hover'\n     *   ],function(_e){\n     *       // 如果hover效果的样式名已经通过data-hover指定\n     *       _e._$hover('abc');\n     *\n     *       // 如果hover效果的样式名没有通过data-hover指定\n     *       _e._$hover('abc','js-hover');\n     *   });\n     * ```\n     *\n     * @method module:util/hover/hover._$hover\n     * @param  {String|Node} arg0 - 节点\n     * @param  {String}      arg1 - 样式，默认为js-hover\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$hover\n     * @see module:util/hover/hover._$hover\n     */\n    _p._$hover = function(_element,_clazz){\n        if (!_u._$isArray(_element)){\n            _element = _e._$get(_element);\n            if (!!_element){\n                _e._$id(_element);\n                _h.__hoverElement(\n                    _element,_clazz||\n                    _e._$dataset(_element,'hover')||\n                    'js-hover'\n                );\n            }\n            return;\n        }\n        // batch hover\n        _u._$forEach(\n            _element,function(_node){\n                _p._$hover(_node,_clazz);\n            }\n        );\n    };\n    /**\n     * 低版本移除节点hover行为，高版本不做处理\n     *\n     * 样式举例\n     * ```css\n     *    .page .element:hover,\n     *    .page .element.js-hover{background:#f00;}\n     * ```\n     *\n     * 结构举例\n     * ```html\n     *    <!-- 使用data-hover指定hover效果的样式名称 -->\n     *    <div id=\"abc\" data-hover=\"js-hover\">aaaaa</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'util/hover/hover'\n     *   ],function(_e){\n     *       // 如果hover效果的样式名已经通过data-hover指定\n     *       _e._$hover('abc');\n     * \n     *       // 移除_$hover接口添加的效果\n     *       _e._$unhover('abc');\n     *   });\n     * ```\n     *\n     * @method module:util/hover/hover._$unhover\n     * @param  {String|Node} arg0 - 节点\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$unhover\n     * @see module:util/hover/hover._$unhover\n     */\n    _p._$unhover = function(_element){\n        if (!_u._$isArray(_element)){\n            var _id = _e._$id(_element);\n            if (!!_id){\n                _h.__unhoverElement(_id);\n            }\n            return;\n        }\n        // batch unhover\n        _u._$forEach(\n            _element,function(_node){\n                _p._$unhover(_node);\n            }\n        );\n    };\n     // for chainable method\n    _x._$merge(_p);\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.e'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/hover/platform/hover.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   \n * ------------------------------------------\n */\nNEJ.define(function(_p,_o,_f,_r){\n    /**\n     * 节点hover行为\n     * @param  {Node}   节点\n     * @param  {String} 样式，默认为js-hover\n     * @return {Void}\n     */\n    _p.__hoverElement = function(){\n        // use css :hover\n    };\n    /**\n     * 移除节点hover行为\n     * @param  {String} 节点ID\n     * @return {Void}\n     */\n    _p.__unhoverElement = function(_id){\n        // use css :hover\n    };\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/hover/platform/hover.patch.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author\n * ------------------------------------------\n */\nNEJ.define([\n    './hover.js',\n    'base/event'\n],function(_h,_v,_p,_o,_f,_r){\n    // TR 2.0 - IE 6\n    // TR 3.0 - IE 7\n    // TR 4.0 - IE 8\n    // TR 5.0 - IE 9\n    // TR 6.0 - IE 10\n    // TR 7.0 - IE 11\n\n    // for ie6-\n    NEJ.patch('TR<=2.0',function(){\n        var _cache = {};\n        // enter element\n        var _doEnter = function(_event){\n            var _element = _event.srcElement,\n                _class = _cache[_element.id],\n                _name = _element.className;\n            if (_name.indexOf(_class)<0){\n                _element.className += ' '+_class;\n            }\n        };\n        // leave element\n        var _doLeave = function(_event){\n            var _element = _event.srcElement,\n                _class = _cache[_element.id],\n                _name = _element.className||'';\n            if (_name.indexOf(_class)>=0){\n                _element.className = _name.replace(_class,'').trim();\n            }\n        };\n        /**\n         * 节点hover行为\n         * @param  {Node}   节点\n         * @param  {String} 样式，默认为js-hover\n         * @return {Void}\n         */\n        _h.__hoverElement = function(_element,_class){\n            var _id = _element.id;\n            if (!!_cache[_id]) return;\n            // hover element\n            _cache[_id] = _class;\n            _v._$addEvent(\n                _id,'mouseenter',_doEnter\n            );\n            _v._$addEvent(\n                _id,'mouseleave',_doLeave\n            );\n        };\n        /**\n         * 移除节点hover行为\n         * @param  {String} 节点ID\n         * @return {Void}\n         */\n        _h.__unhoverElement = function(_id){\n            if (!_cache[_id]) return;\n            delete _cache[_id];\n            _v._$delEvent(\n                _id,'mouseenter',_doEnter\n            );\n            _v._$delEvent(\n                _id,'mouseleave',_doLeave\n            );\n        };\n    });\n\n    return _h;\n});\n"
  },
  {
    "path": "src/util/hover/test/hover.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>hover测试页</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n        <style>\n        \t#box input:hover,#box div:hover,#box p:hover,#box textarea:hover,#box select:hover,#box a:hover{background:red;}\n        \t.js-hover{background:green;}\n        </style>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit hover test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n \t\t<div id=\"box\">\n \t\t\t<input type='text' value='text' />\n \t\t\t<input type='redio' />\n \t\t\t<input type='password' value='text' />\n \t\t\t<input type='checkbox' />\n \t\t\t<textarea>textarea</textarea>\n \t\t\t<div>div</div>\n \t\t\t<a>a</a>\n \t\t\t<p>p</p>\n \t\t\t<select>\n \t\t\t\t<option>1</option>\n \t\t\t\t<option>2</option>\n \t\t\t</select>\n \t\t\t<code>\n \t\t\t\tjavascript\n \t\t\t</code>\n \t\t</div>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./hover.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/util/hover/test/hover.test.js",
    "content": "NEJ.define([\n    'base/element',\n    'util/hover/hover'\n],function(_e,_t){\n    var _v = NEJ.P('nej.v');\n\t//开始单元测试\n    test('元素hover测试', function() {\n        expect(10);\n        var _list = _e._$getChildren(_e._$get('box'));\n        for (var i = _list.length-1; i >=0; i--){\n        \tvar _i = _list[i];\n        \t_t._$hover(_i,'js-hover');\n            _v._$dispatchEvent(_list[i],'mouseenter');\n            equal(_list[i].className.indexOf('js-hover')>-1,true,'样式加上去了');\n        }\n    });\n});\n"
  },
  {
    "path": "src/util/lazy/demo/image.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - 图片延时载入</title>\n    <meta charset=\"utf-8\" />\n    <style>\n      .box{height:500px;overflow:auto;border:1px solid #aaa;}\n      .box p{margin:20px 0;}\n      .box img{height:200px;}\n    </style>\n  </head>\n  <body>\n    \n    <div class=\"box\" id=\"abc\">\n      <p><img src=\"../../../../res/nej_blank.gif\" data-src=\"http://h.hiphotos.baidu.com/image/pic/item/aec379310a55b319cca6657441a98226cffc1757.jpg\"/></p>\n      <p><img src=\"../../../../res/nej_blank.gif\" data-src=\"http://a.hiphotos.baidu.com/image/pic/item/b64543a98226cffc96cffcadbb014a90f703eacc.jpg\"/></p>\n      <p><img src=\"../../../../res/nej_blank.gif\" data-src=\"http://h.hiphotos.baidu.com/image/pic/item/241f95cad1c8a786ce85ce076509c93d70cf500f.jpg\"/></p>\n      <p><img src=\"../../../../res/nej_blank.gif\" data-src=\"http://f.hiphotos.baidu.com/image/pic/item/5882b2b7d0a20cf4cccab9d774094b36acaf9964.jpg\"/></p>\n      <p><img src=\"../../../../res/nej_blank.gif\" data-src=\"http://a.hiphotos.baidu.com/image/pic/item/dc54564e9258d109e35ecfbad358ccbf6c814d7c.jpg\"/></p>\n      <p><img src=\"../../../../res/nej_blank.gif\" data-src=\"http://a.hiphotos.baidu.com/image/pic/item/32fa828ba61ea8d315e38903950a304e241f58f0.jpg\"/></p>\n      <p><img src=\"../../../../res/nej_blank.gif\" data-src=\"http://c.hiphotos.baidu.com/image/pic/item/6a600c338744ebf838f97637dbf9d72a6059a729.jpg\"/></p>\n      <p><img src=\"../../../../res/nej_blank.gif\" data-src=\"http://e.hiphotos.baidu.com/image/pic/item/a9d3fd1f4134970a543a6a3197cad1c8a7865d66.jpg\"/></p>\n      <p><img src=\"../../../../res/nej_blank.gif\" data-src=\"http://d.hiphotos.baidu.com/image/pic/item/0df3d7ca7bcb0a461988e8316963f6246b60af14.jpg\"/></p>\n      <p><img src=\"../../../../res/nej_blank.gif\" data-src=\"http://h.hiphotos.baidu.com/image/pic/item/3ac79f3df8dcd10075e23f28708b4710b9122fb9.jpg\"/></p>\n    </div>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            '../image.js'\n        ],function(_t){\n            _t._$$LazyImage._$allocate({\n                parent:'abc',\n                attr:'src'\n            });\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/lazy/image.js",
    "content": "/*\n * ------------------------------------------\n * 延时加载图片控件实现文件 \n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/lazy/image */\nNEJ.define([\n    'base/klass',\n    'base/constant',\n    'base/element',\n    './loading.js'\n],function(_k,_g,_e,_t,_p,_o,_f,_r,_pro){\n    /**\n     * 延时加载图片\n     * \n     * @class   module:util/lazy/image._$$LazyImage\n     * @extends module:util/lazy/loading._$$LazyLoading\n     * \n     * @param    {Object} config - 配置信息\n     * @property {String} holder - 图片占位地址，默认为空白图片\n     * \n     */\n    _p._$$LazyImage = _k._$klass();\n    _pro = _p._$$LazyImage._$extend(_t._$$LazyLoading);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/lazy/image._$$LazyImage#__reset\n     * @param  {Object} arg0 - 配置信息\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__holder = _options.holder||_g._$BLANK_IMAGE;\n    };\n    /**\n     * 取待验证资源列表\n     * \n     * @protected\n     * @method module:util/lazy/image._$$LazyImage#__getResourceList\n     * @param  {Node} arg0 - 滚动条所在容器节点\n     * @return {Void}\n     */\n    _pro.__getResourceList = function(_parent){\n        return _parent.getElementsByTagName('img');\n    };\n    /**\n     * 验证资源是否需要做处理\n     * \n     * @protected\n     * @method module:util/lazy/image._$$LazyImage#__getResourceList\n     * @param  {Node}   arg0 - 资源节点\n     * @param  {Object} arg1 - 滚动容器节点\n     * @return {Number}        操作标识，-1 - 移除，0 - 不做处理， 1 - 追加到页面\n     */\n    _pro.__doCheckResource = function(_target,_parent){\n        var _ch = _parent.clientHeight,\n            _top = _e._$offset(_target,_parent).y-_parent.scrollTop,\n            _bottom = _top+_target.offsetHeight,\n            _config = this.__getSettingInfo(_target),\n            // not src\n            // src is blank image\n            // src not equal to data-src\n            _holded = !_target.src||\n                       _target.src.indexOf(this.__holder)>=0||\n                       _target.src.indexOf(_config.src)<0;\n        // check resource append\n        if (_holded&&0<=_bottom&&_top<=_ch){\n            return 1;\n        }\n        // check resource remove\n        if (!_holded&&(_bottom<0||_top>_ch)){\n            return -1;\n        }\n        // do nothing\n        return 0;\n    };\n    /**\n     * 移除资源\n     * \n     * @protected\n     * @method module:util/lazy/image._$$LazyImage#__doRemoveResource\n     * @param  {Node} arg0 - 资源节点\n     * @return {Void}\n     */\n    _pro.__doRemoveResource = function(_node){\n        _node.src = this.__holder;\n    };\n    /**\n     * 添加资源\n     * \n     * @protected\n     * @method module:util/lazy/image._$$LazyImage#__doAppendResource\n     * @param  {Node}   arg0 - 资源节点\n     * @param  {Object} arg1 - 配置信息\n     * @return {Void}\n     */\n    _pro.__doAppendResource = function(_node,_conf){\n        _node.src = _conf.src||this.__holder;\n    };\n});\n"
  },
  {
    "path": "src/util/lazy/loading.js",
    "content": "/*\n * ------------------------------------------\n * 延时加载控件基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/lazy/loading */\nNEJ.define([\n    'base/klass',\n    'base/element',\n    'base/util',\n    'util/event'\n],function(_k,_e,_u,_t,_p,_o,_f,_r,_pro){\n    /**\n     * 延时加载控件基类\n     * \n     * @class   module:util/lazy/loading._$$LazyLoading\n     * @extends module:util/event._$$EventTarget\n     * \n     * @config   {Object}      config - 配置信息\n     * @property {Node|String} parent - 滚动条所在容器，默认为根结点\n     * @property {String}      attr   - 属性标识名称，多个值用逗号分隔，如src则表示需要用到的信息在data-src上\n     */\n    /** \n     * 资源检测触发事件\n     * \n     * @event    module:util/lazy/loading._$$LazyLoading#oncheck\n     * @param    {Object}  event   - 事件信息\n     * @property {Node}    target  - 资源节点\n     * @property {Object}  config  - 滚动容器信息，scrollTop/clientHeight...\n     * @property {Number}  value   - 操作标识，-1 - 移除，0 - 不做处理， 1 - 追加到页面\n     */\n    /** \n     * 资源从页面移除触发事件\n     * \n     * @event    module:util/lazy/loading._$$LazyLoading#onremove\n     * @param    {Object}  event   - 事件信息\n     * @property {Node}    target  - 资源节点\n     * @property {Object}  config  - attr属性指定的配置信息\n     * @property {Boolean} stopped - 是否阻止后续逻辑\n     */\n    /** \n     * 资源追加到页面触发事件\n     * \n     * @event    module:util/lazy/loading._$$LazyLoading#onappend\n     * @param    {Object}  event   - 事件信息\n     * @property {Node}    target  - 资源节点\n     * @property {Object}  config  - attr属性指定的配置信息\n     * @property {Boolean} stopped - 是否阻止后续逻辑\n     */\n    _p._$$LazyLoading = _k._$klass();\n    _pro = _p._$$LazyLoading._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/lazy/loading._$$LazyLoading#__reset\n     * @param  {Object} arg0 - 配置信息\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__name = _options.attr||'';\n        this.__parent = _e._$get(_options.parent);\n        this.__doInitDomEvent([[\n            this.__parent||window,'scroll',\n            this.__doCheckScrollPosition._$bind(this)\n        ]]);\n        this._$refresh();\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/lazy/loading._$$LazyLoading#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        delete this.__parent;\n        this.__super();\n    };\n    /**\n     * 取滚动视图\n     * \n     * @protected \n     * @method module:util/lazy/loading._$$LazyLoading#__getScrollViewPort\n     * @return {Object} 滚动视图信息\n     */\n    _pro.__getScrollViewPort = function(){\n        return this.__parent||_e._$getPageBox();\n    };\n    /**\n     * 取配置信息\n     * \n     * @protected\n     * @method module:util/lazy/loading._$$LazyLoading#__getSettingInfo\n     * @param  {Node} arg0 - 节点\n     * @return {Object}      配置信息\n     */\n    _pro.__getSettingInfo = function(_node){\n        var _ret = {};\n        _u._$forEach(\n            this.__name.split(','),function(_name){\n                _ret[_name] = _e._$dataset(_node,_name);\n            }\n        );\n        return _ret;\n    };\n    /**\n     * 滚动检测\n     * \n     * @protected\n     * @method module:util/lazy/loading._$$LazyLoading#__doCheckScrollPosition\n     * @return {Void}\n     */\n    _pro.__doCheckScrollPosition = (function(){\n        var _nmap = {\n            '-1':'onremove',\n             '1':'onappend'\n        };\n        return function(_event){\n            var _list = this.__getResourceList(\n                this.__parent||document\n            );\n            var _pbox = this.__getScrollViewPort();\n            _u._$forEach(\n                _list,function(_node){\n                    // check node\n                    var _eobj = {\n                        target:_node,\n                        config:_pbox\n                    };\n                    this._$dispatchEvent('oncheck',_eobj);\n                    // check action result\n                    var _ret = _eobj.value;\n                    if (_ret==null){\n                        _ret = this.__doCheckResource(_node,_pbox);\n                    }\n                    var _name = _nmap[_ret];\n                    if (!_name){\n                        return;\n                    }\n                    // check action\n                    var _eobj = {\n                        target:_node,\n                        config:this.__getSettingInfo(_node)\n                    };\n                    this._$dispatchEvent(_name,_eobj);\n                    if (!!_eobj.stopped){\n                        return;\n                    }\n                    // do action\n                    if (_ret==-1){\n                        this.__doRemoveResource(_node);\n                    }else{\n                        this.__doAppendResource(\n                            _node,_eobj.config\n                        );\n                    }\n                },this\n            );\n        };\n    })();\n    /**\n     * 取待验证资源列表，子类实现具体逻辑\n     * \n     * @abstract\n     * @method module:util/lazy/loading._$$LazyLoading#__getResourceList\n     * @param  {Node} arg0 - 滚动条所在容器节点\n     * @return {Void}\n     */\n    _pro.__getResourceList = _f;\n    /**\n     * 验证资源是否需要做处理，子类实现具体逻辑\n     * \n     * @abstract\n     * @method module:util/lazy/loading._$$LazyLoading#__getResourceList\n     * @param  {Node}   arg0 - 资源节点\n     * @param  {Object} arg1 - 滚动容器节点\n     * @return {Number}        操作标识，-1 - 移除，0 - 不做处理， 1 - 追加到页面\n     */\n    _pro.__doCheckResource = _f;\n    /**\n     * 移除资源，子类实现具体逻辑\n     * \n     * @abstract\n     * @method module:util/lazy/loading._$$LazyLoading#__doRemoveResource\n     * @param  {Node} arg0 - 资源节点\n     * @return {Void}\n     */\n    _pro.__doRemoveResource = _f;\n    /**\n     * 添加资源，子类实现具体逻辑\n     * \n     * @abstract\n     * @method module:util/lazy/loading._$$LazyLoading#__doAppendResource\n     * @param  {Node}   arg0 - 资源节点\n     * @param  {Object} arg1 - 配置信息\n     * @return {Void}\n     */\n    _pro.__doAppendResource = _f;\n    /**\n     * 强制刷新检测资源\n     * \n     * @method module:util/lazy/loading._$$LazyLoading#_$refresh\n     * @return {Void}\n     */\n    _pro._$refresh = function(){\n        this.__doCheckScrollPosition();\n    };\n});\n"
  },
  {
    "path": "src/util/lightbox/demo/lightbox.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - LightBox</title>\n    <meta charset=\"utf-8\" />\n    <style>\n        p img{height:100px;cursor:pointer;}\n    </style>\n  </head>\n  <body>\n    \n    <div id=\"abc\">\n      <p><img src=\"http://www0.autoimg.cn/newspic/2014/11/5/620x0_0_2014110509182432121.jpg\" data-src=\"http://www0.autoimg.cn/newspic/2014/11/5/620x0_0_2014110509182432121.jpg\" alt=\"汽车1\"/></p>\n      <p><img src=\"http://car0.autoimg.cn/carnews/2014/11/5/d_20141105222115648413111.jpg\" data-src=\"http://car0.autoimg.cn/carnews/2014/11/5/d_20141105222115648413111.jpg\" alt=\"汽车2\"/></p>\n      <p><img src=\"http://car0.autoimg.cn/carnews/2014/11/5/d_20141105225127858413110.jpg\" data-src=\"http://car0.autoimg.cn/carnews/2014/11/5/d_20141105225127858413110.jpg\" alt=\"汽车3\"/></p>\n      <p><img src=\"http://car0.autoimg.cn/carnews/2014/11/5/d_20141105222113075413110.jpg\" data-src=\"http://car0.autoimg.cn/carnews/2014/11/5/d_20141105222113075413110.jpg\" alt=\"汽车4\"/></p>\n      <p><img src=\"http://car0.autoimg.cn/carnews/2014/11/5/d_20141105222104682413110.jpg\" data-src=\"http://car0.autoimg.cn/carnews/2014/11/5/d_20141105222104682413110.jpg\" alt=\"汽车5\"/></p>\n    </div>\n    <hr/>\n    <div id=\"efg\">\n      <p><img data-group=\"a\" src=\"http://www0.autoimg.cn/newspic/2014/11/5/620x0_0_2014110509182432121.jpg\" data-src=\"http://www0.autoimg.cn/newspic/2014/11/5/620x0_0_2014110509182432121.jpg\" alt=\"汽车1\"/></p>\n      <p><img data-group=\"a\" src=\"http://car0.autoimg.cn/carnews/2014/11/5/d_20141105222115648413111.jpg\" data-src=\"http://car0.autoimg.cn/carnews/2014/11/5/d_20141105222115648413111.jpg\" alt=\"汽车2\"/></p>\n      <p><img data-group=\"a\" src=\"http://car0.autoimg.cn/carnews/2014/11/5/d_20141105225127858413110.jpg\" data-src=\"http://car0.autoimg.cn/carnews/2014/11/5/d_20141105225127858413110.jpg\" alt=\"汽车3\"/></p>\n      <p><img data-group=\"a\" src=\"http://car0.autoimg.cn/carnews/2014/11/5/d_20141105222113075413110.jpg\" data-src=\"http://car0.autoimg.cn/carnews/2014/11/5/d_20141105222113075413110.jpg\" alt=\"汽车4\"/></p>\n      <p><img data-group=\"a\" src=\"http://car0.autoimg.cn/carnews/2014/11/5/d_20141105222104682413110.jpg\" data-src=\"http://car0.autoimg.cn/carnews/2014/11/5/d_20141105222104682413110.jpg\" alt=\"汽车5\"/></p>\n    </div>\n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            'util/lightbox/lightbox'\n        ],function(_t){\n            var _inst0 = _t._$$LightBox._$allocate({\n                parent:'abc'\n            });\n            \n            var _inst1 = _t._$lightbox({\n                parent:'efg'\n            });\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/lightbox/lightbox.js",
    "content": "/*\n * ------------------------------------------\n * 图片幻灯片控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/lightbox/lightbox */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    'base/event',\n    'base/element',\n    'util/event',\n    'ui/lightbox/lightbox'\n],function(NEJ,_k,_u,_v,_e,_t,_i,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 图片幻灯片控件\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"abc\">\n     *   <p><img src=\"./a.jpg\" data-src=\"./a.jpg\" alt=\"汽车1\"/></p>\n     *   <p><img src=\"./b.jpg\" data-src=\"./b.jpg\" alt=\"汽车2\"/></p>\n     *   <p><img src=\"./c.jpg\" data-src=\"./c.jpg\" alt=\"汽车3\"/></p>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     *  NEJ.define([\n     *      'util/lightbox/lightbox'\n     *  ],function(_t){\n     *      // 单张图片显示\n     *      _t._$$LightBox._$allocate({\n     *          parent:'abc'\n     *      });\n     *  });\n     * ```\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"def\">\n     *   <p><img src=\"./a.jpg\" data-group=\"a\" data-src=\"./a.jpg\" alt=\"汽车1\"/></p>\n     *   <p><img src=\"./b.jpg\" data-group=\"a\" data-src=\"./b.jpg\" alt=\"汽车2\"/></p>\n     *   <p><img src=\"./c.jpg\" data-group=\"a\" data-src=\"./c.jpg\" alt=\"汽车3\"/></p>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     *  NEJ.define([\n     *      'util/lightbox/lightbox'\n     *  ],function(_t){\n     *      // 分组图片显示\n     *      _t._$$LightBox._$allocate({\n     *          parent:'def'\n     *      });\n     *  });\n     * ```\n     * \n     * @class    module:util/lightbox/lightbox._$$LightBox\n     * @extends  module:util/event._$$EventTarget\n     *\n     * @param    {Object}       config   - 可选配置参数\n     * @property {String|Node}  parent   - 用于搜索图片的容器节点，默认为document.body\n     * @property {String}       clazz    - 幻灯片样式名称\n     * @property {String}       mask     - 遮罩样式名称\n     * @property {String}       loading  - 图片加载中样式名称，默认为js-loading\n     * @property {String}       disabled - 按钮禁用样式名称，默认为js-disabled\n     */\n    /**\n     * 请求播放幻灯片\n     * \n     * @event    module:util/lightbox/lightbox._$$LightBox#onlightbox\n     * @param    {Object} event  - 事件信息\n     * @property {Number} index  - 当前图片索引值\n     * @property {Array}  list   - 用于幻灯片播放的图片列表\n     */\n    _p._$$LightBox = _k._$klass();\n    _pro = _p._$$LightBox._$extend(_t._$$EventTarget);\n    /**\n     * 控件初始化\n     *\n     * @protected \n     * @method module:util/lightbox/lightbox._$$LightBox#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__lopt = {\n            parent:document.body\n        };\n        this.__super();\n    };\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/lightbox/lightbox._$$LightBox#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        // default lightbox\n        this._$setEvent(\n            'onlightbox',\n            this.__onLightBoxShow._$bind(this)\n        );\n        this.__super(_options);\n        // init config\n        _u._$merge(\n            this.__lopt,\n            _u._$fetch({\n                mask:null,clazz:null,\n                loading:null,disabled:null\n            },_options)\n        );\n        // init event\n        this.__parent = _e._$get(_options.parent);\n        this.__doInitDomEvent([[\n            this.__parent,'click',\n            this.__onCheckImage._$bind(this)\n        ]]);\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/lightbox/lightbox._$$LightBox#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        delete this.__parent;\n        this.__super();\n    };\n    /**\n     * 图片点击事件\n     * \n     * @protected\n     * @method module:util/lightbox/lightbox._$$LightBox#__onCheckImage\n     * @param  {Event} arg0 - 事件信息\n     * @return {Void}\n     */\n    _pro.__onCheckImage = (function(){\n        var _doDumpImage = function(_img){\n            return {\n                group:_e._$dataset(_img,'group'),\n                src:_e._$dataset(_img,'src')||_img.src,\n                title:_img.alt||_e._$dataset(_img,'title')\n            };\n        };\n        return function(_event){\n            var _element = _v._$getElement(_event);\n            if (_element.tagName!='IMG') return;\n            _v._$stop(_event);\n            var _iobj = _doDumpImage(_element);\n            // for single image\n            if (!_iobj.group){\n                this._$dispatchEvent(\n                    'onlightbox',{\n                        index:0,\n                        list:[_iobj]\n                    }\n                );\n                return;\n            }\n            // for group image\n            // dump image list\n            var _list = [],\n                _index = 0;\n            _u._$forEach(\n                this.__parent.getElementsByTagName('img'),\n                function(_img){\n                    var _data = _doDumpImage(_img);\n                    if (_data.group===_iobj.group){\n                        _list.push(_data);\n                        if (_element==_img){\n                            _index = _list.length-1;\n                        }\n                    }\n                }\n            );\n            // trigger lightbox show\n            this._$dispatchEvent(\n                'onlightbox',{\n                    index:_index,\n                    list:_list\n                }\n            );\n        };\n    })();\n    /**\n     * 默认显示图片幻灯片逻辑，子类可重写\n     * \n     * @protected\n     * @method module:util/lightbox/lightbox._$$LightBox#__onLightBoxShow\n     * @param  {Object} arg0 - 图片信息\n     * @return {Void}\n     */\n    _pro.__onLightBoxShow = function(_event){\n        this.__lopt.list = _event.list;\n        this.__lopt.index = _event.index;\n        _i._$$LightBox._$allocate(this.__lopt);\n    };\n    /**\n     * 幻灯片播放API\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"def\">\n     *   <p><img src=\"./a.jpg\" data-group=\"a\" data-src=\"./a.jpg\" alt=\"汽车1\"/></p>\n     *   <p><img src=\"./b.jpg\" data-group=\"a\" data-src=\"./b.jpg\" alt=\"汽车2\"/></p>\n     *   <p><img src=\"./c.jpg\" data-group=\"a\" data-src=\"./c.jpg\" alt=\"汽车3\"/></p>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     *  NEJ.define([\n     *      'util/lightbox/lightbox'\n     *  ],function(_t){\n     *      // 分组图片显示\n     *      var _inst = _t._$lightbox({\n     *          parent:'def'\n     *      });\n     *  });\n     * ```\n     * \n     * @method module:util/lightbox/lightbox._$lightbox\n     * @param  {Object} arg0 - 配置信息，同幻灯片控件的构造参数\n     * @return {module:util/lightbox/lightbox._$$LightBox} 幻灯片实例\n     */\n    _p._$lightbox = function(_options){\n        return _p._$$LightBox._$allocate(_options);\n    };\n    \n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/list/demo/data.js",
    "content": "define([\n    'base/klass',\n    'util/cache/abstract'\n],function(_k,_d,_p,_pro){\n\n    _p._$$Cache = _k._$klass();\n    _pro = _p._$$Cache._$extend(_d._$$CacheListAbstract);\n\n    /**\n     * ӷбʵ־߼\n     *\n     * @abstract\n     * @method   module:util/cache/abstract._$$CacheListAbstract#__doLoadList\n     * @param    {Object}   arg0   - Ϣ\n     * @property {String}   key    - бʶ\n     * @property {Number}   offset - ƫ\n     * @property {Number}   limit  - \n     * @property {String}   data   - \n     * @property {Function} onload - бص\n     * @return   {Void}\n     */\n    var x = 0;\n    _pro.__doLoadList = function(_options){\n        if (!x){\n            console.log('request from server');\n            x = 1;\n            var _ret = [];\n            for(var i= 0;i<_options.limit;i++){\n                _ret.push({\n                    id:_options.offset+i,\n                    name:'test-'+(+new Date)\n                });\n            }\n            _options.onload({\n                total:300,\n                result:_ret\n            });\n            return;\n        }\n        _options.onload(null);\n        this._$dispatchEvent('onerror');\n        //_options.onload([]);\n    };\n\n    return _p;\n});"
  },
  {
    "path": "src/util/list/demo/list/cache.js",
    "content": "NEJ.define([\n\t'base/klass',\n\t'base/event',\n\t'util/event/event',\n\t'util/cache/abstract'\n],function(_k,_v,_z,_t,_p,_pro){\n\t/**\n\t *\n\t */\n\t_p._$$CustomCache = _k._$klass();\n\t_pro = _p._$$CustomCache._$extend(_t._$$CacheListAbstract);\n\t/**\n\t *\n\t * @param _options\n\t * @private\n\t */\n\t_pro.__doLoadList = function(_options){\n\n\t\t// for test\n\t\tvar _arr = [],\n\t\t\t_total = 104,\n\t\t\t_count = Math.floor(_total/_options.limit),\n\t\t\t_number = _count*_options.limit;\n\t\tvar _len = _options.offset>=_number?_total-_number:_options.limit;\n\t\tfor(var i=0;i<_total;i++){\n\t\t\t_arr.push({id:+new Date+i,name:'user-'+(+new Date+i),loginTime:+new Date});\n\t\t}\n\t\tif (_options.offset==0){\n\t\t\tthis._$setTotal(_options.key,_total);\n\t\t}\n\t\twindow.setTimeout(_options.onload._$bind(_options,_arr),1000);\n\n\t};\n\t/**\n\t * 从服务器上删除列表项，子类实现具体逻辑\n\t * @protected\n\t * @method {__doDeleteItem}\n\t * @param   {Object}   请求信息\n\t * @config  {String}   key      列表标识\n\t * @config  {Number}   id       列表项标识\n\t * @config  {String}   data     请求相关数据\n\t * @config  {Function} onload   列表项载入回调\n\t * @return {Void}\n\t */\n\t_pro.__doDeleteItem = function(_options){\n\t\t/*\n\t\t _j._$request(\n\t\t '/rest/data/delete',{\n\t\t // ...\n\t\t onload:function(_json){\n\t\t // remove from cache\n\t\t var _event = _options.onload(!0);\n\t\t // refresh list view\n\t\t _v._$dispatchEvent(\n\t\t _p._$$CustomCache,\n\t\t 'listchange',_event\n\t\t );\n\t\t }\n\t\t }\n\t\t );\n\t\t */\n\t\t// for test\n\t\twindow.setTimeout(function(){\n\t\t\tvar _event = _options.onload(!0);\n\t\t\t_v._$dispatchEvent(\n\t\t\t\t_p._$$CustomCache,\n\t\t\t\t'listchange',_event\n\t\t\t);\n\t\t},500);\n\t};\n\n\t/**\n\t * 从服务器上删除列表项，子类实现具体逻辑\n\t * @protected\n\t * @method {__doDeleteItem}\n\t * @param   {Object}   请求信息\n\t * @config  {String}   key      列表标识\n\t * @config  {Number}   id       列表项标识\n\t * @config  {String}   data     请求相关数据\n\t * @config  {Function} onload   列表项载入回调\n\t * @return {Void}\n\t */\n\t_pro.__doUpdateItem = function(_options){\n\n\t\t// for test\n\t\twindow.setTimeout(function(){\n\t\t\t_options.data.name = 'up-'+(+new Date);\n\t\t\tvar _event = _options.onload(_options.data);\n\t\t\t_v._$dispatchEvent(\n\t\t\t    _p._$$CustomCache,\n\t\t\t\t'listchange',_event\n\t\t\t);\n\t\t},500);\n\n\t};\n\n\t_z._$$CustomEvent._$allocate({\n\t\telement:_p._$$CustomCache,\n\t\tevent:'listchange'\n\t});\n\n\treturn _p;\n});\n"
  },
  {
    "path": "src/util/list/demo/list/item.js",
    "content": "NEJ.define([\n    'base/klass',\n    'base/util',\n    'base/event',\n    'base/element',\n    'ui/item/list',\n    'util/template/tpl',\n    'text!./ntp.html'\n],function(_k,_u,_v,_e,_i,_t,_html,_p,_pro){\n    /**\n     *\n     */\n    _p._$$Item = NEJ.C();\n    _pro = _p._$$Item._$extend(_i._$$ListItem);\n    /**\n     *\n     * @param _options\n     * @private\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__doInitDomEvent(this.__xxev);\n    };\n    /**\n     * 初始化模版\n     */\n    _pro.__initXGui = (function(){\n        var _seed = _t._$addNodeTemplate(_html);\n        return function() {\n            this.__seed_html = _seed;\n        };\n    })();\n    /**\n     *\n     */\n    _pro.__initNode = function(){\n        this.__super();\n        var _list = _e._$getByClassName(\n            this.__body,'js-flag'\n        );\n        this.__nbox = _list[2];\n        this.__xxev = [[\n            _list[0],'click',this.__onDelete._$bind(this)\n        ],[\n            _list[1],'click',this.__onUpdate._$bind(this)\n        ]];\n    };\n    /**\n     *\n     * @param _event\n     * @private\n     */\n    _pro.__onDelete = function(_event){\n        _v._$stop(_event);\n        this.__super();\n    };\n    /**\n     *\n     * @param _event\n     * @private\n     */\n    _pro.__onUpdate = function(_event){\n        _v._$stop(_event);\n        this.__super();\n    };\n    /**\n     * 刷新项,子类实现具体逻辑\n     * @protected\n     * @method {__doRefresh}\n     * @return {Void}\n     */\n    _pro.__doRefresh = function(_data){\n        this.__nbox.innerText =\n            this.__index+'. '+_data.name+'：'+\n            _u._$format(_data.loginTime,'yyyy-MM-dd HH:mm:ss');\n    };\n});"
  },
  {
    "path": "src/util/list/demo/list/jst.html",
    "content": "{list beg..end as y}\n{var x=xlist[y]}\n<div class=\"itm\" id=\"${x.id|seed}\">\n    <a class=\"fr\" href=\"#\" data-id=\"${x.id}\" data-action=\"delete\">[删除]</a>\n    <a class=\"fr\" href=\"#\" data-id=\"${x.id}\" data-action=\"update\">[更新]</a>\n    <p>${beg+y_index}. ${x.name}：${x.loginTime|format:'yyyy-MM-dd HH:mm:ss'}</p>\n</div>\n{/list}"
  },
  {
    "path": "src/util/list/demo/list/ntp.html",
    "content": "<div class=\"itm\">\n    <a class=\"fr js-flag\" href=\"#\">[删除]</a>\n    <a class=\"fr js-flag\" href=\"#\">[更新]</a>\n    <p class=\"js-flag\"></p>\n</div>"
  },
  {
    "path": "src/util/list/demo/list/wf.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test list module</title>\n    <meta charset=\"utf-8\"/>\n    <style>\n      *{border:0;padding:0;margin:0;}\n      html,body{width:100%;height:100%;}\n      .fl{float:left;width:40%;padding-bottom:50px;}\n      .fr{float:right;}\n      .itm{margin:10px 0;overflow:hidden;}\n      .itm p{margin:0 150px 0 0;}\n      .itm a{margin-right:15px;font-size:12px;}\n    </style>\n  </head>\n  <body>\n    <div class=\"fl xx\">\n      <h1>JST模版</h1>\n      <input type=\"button\" value=\"prev\" id=\"btnprev\"/>\n      <input type=\"button\" value=\"next\" id=\"btnnext\"/>\n      <div id=\"list-box-0\"></div>\n      <div id=\"more-btn-0\"> load more </div>\n      <div id=\"page-box-0\"></div>\n    </div>\n    <div class=\"fl xx\">\n      <h1>ITEM模版</h1>\n      <div id=\"list-box-1\"></div>\n      <div id=\"more-btn-1\"> load more </div>\n    </div>\n    <script src=\"../../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            'base/event',\n            'util/template/jst',\n            'util/list/waterfall',\n            './cache.js',\n            './item.js',\n            'text!./jst.html'\n        ], function (_v, _l, _t, _d, _i, _html) {\n\n          var jstkey = _l._$add(_html);\n          \n          var mdl = _t._$$ListModuleWF._$allocate({\n              limit:20,\n              \n              count:2,      // 加载多少次出现分页器\n              delta:200,    // 滚动距离底部多少像素触发加载更多\n              sbody:window, // 包含列表的滚动条所在容器节点或者ID\n              \n              parent:'list-box-0',\n              //more:'more-btn-0',\n              item:jstkey,\n              pager:{parent:'page-box-0'},\n              cache:{klass:_d._$$CustomCache,lkey:'test-list'},\n              onupdate:function(_event){\n                  console.log('update from jst -> '+_event.data.id);\n                  this._$update({\n                      id:_event.data.id,\n                      name:'xxx-'+(+new Date),\n                      loginTime:+new Date\n                  });\n              },\n              ondelete:function(_event){\n                  console.log('delete from jst -> '+_event.data.id);\n                  this._$delete(_event.data);\n              },\n              onpagechange:function(_event){\n                  console.log('go page -> '+_event.index);\n              }\n          });\n\n            _v._$addEvent(\n                'btnprev','click',function(){\n                        mdl._$prevPage();\n                }\n            );\n            _v._$addEvent(\n                'btnnext','click',function(){\n                    mdl._$nextPage();\n                }\n            );\n\n\n          _t._$$ListModuleWF._$allocate({\n              limit:20,\n              parent:'list-box-1',\n              more:'more-btn-1',\n              item:{klass:_i._$$Item},\n              cache:{klass:_d._$$CustomCache,lkey:'test-list'},\n              onupdate:function(_event){\n                  console.log('update from item -> '+_event.data.id);\n                  this._$update({\n                      id:_event.data.id,\n                      name:'xxx-'+(+new Date),\n                      loginTime:+new Date\n                  });\n              },\n              ondelete:function(_event){\n                  console.log('delete from item -> '+_event.data.id);\n                  this._$delete(_event.data);\n              }\n          });\n\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/list/demo/page.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - Waterfall list</title>\n    <meta charset=\"utf-8\" />\n    <style>\n        .lbox{min-height:100px;border:1px solid #aaa;}\n        .lbox .itm{text-align:left;margin:10px 0;}\n    </style>\n  </head>\n  <body>\n\n    <div id=\"module-box\" class=\"lbox\"></div>\n    <div id=\"pager-box\"></div>\n\n    <div id=\"template-box\" style=\"display:none;\">\n      <textarea name=\"jst\" id=\"jst-list\">\n        {list beg..end as y}\n          {var x = xlist[y]}\n          <div class=\"itm\">${x.id} - ${x.name}</div>\n        {/list}\n      </textarea>\n    </div>\n\n    <script src=\"../../../define.js\"></script>\n    <script>\n        define([\n            './data.js',\n            'util/template/tpl',\n            'util/list/page',\n            'ui/pager/simple'\n        ],function(_d,_e,_t,ui){\n            _e._$parseTemplate('template-box');\n            var module = _t._$$ListModulePG._$allocate({\n                limit:10,\n                parent:'module-box',\n                pager:{parent:'pager-box',klass:ui._$$SimplePager,beg:true,end:true},\n                more:'btn-more',\n                item:'jst-list',\n                cache:{lkey:'data-list',klass:_d._$$Cache},\n                onlistloaderror:function(event){\n                    console.log('list error');\n                    event.parent.innerHTML = '<p>列表载入失败</p>';\n                },\n                onafterlistrender:function(){\n                    console.log('after list load')\n                }\n            });\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/list/demo/waterfall.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - Waterfall list</title>\n    <meta charset=\"utf-8\" />\n    <style>\n        .lbox{min-height:100px;border:1px solid #aaa;}\n        .lbox .itm{text-align:left;margin:10px 0;}\n    </style>\n  </head>\n  <body>\n\n    <div id=\"module-box\" class=\"lbox\"></div>\n\n    <div id=\"template-box\" style=\"display:none;\">\n      <textarea name=\"jst\" id=\"jst-list\">\n        {list beg..end as y}\n          {var x = xlist[y]}\n          <div class=\"itm\">${x.id} - ${x.name}</div>\n        {/list}\n      </textarea>\n    </div>\n\n    <script src=\"../../../define.js\"></script>\n    <script>\n        define([\n            './data.js',\n            'util/template/tpl',\n            'util/list/waterfall'\n        ],function(_d,_e,_t){\n            _e._$parseTemplate('template-box');\n            var module = _t._$$ListModuleWF._$allocate({\n                limit:10,\n                parent:'module-box',\n                item:'jst-list',\n                cache:{lkey:'data-list',klass:_d._$$Cache},\n                sbody:window,\n                onlistloaderror:function(){\n                    document.body.onclick = function(){\n                        module._$refresh();\n                    };\n                }\n            });\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/list/holder.js",
    "content": "/*\n * ------------------------------------------\n * 列表占位控件基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/list/holder */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    'base/element',\n    'util/event'\n],function(NEJ,_k,_u,_e,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 列表占位控件\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"scroll-body\">\n     *   <div>\n     *     <!-- content here -->\n     *   </div>\n     *   <ul>\n     *     <li>xxxxxxx</li>\n     *     <li>xxxxxxx</li>\n     *   </ul>\n     * </div>\n     * ```\n     * \n     * @class    module:util/list/holder._$$ListHolder\n     * @extends  module:util/event._$$EventTarget\n     *\n     * @param    {Object}       config - 可选配置参数\n     * @property {String|Node}  sbody  - 滚动容器节点\n     * @property {String|Node}  hbody  - 占位容器节点，默认使用滚动容器节点\n     * @property {Number|Array} limit  - 可视区域外保留列表项数量控制，通过传入数组控制不同的上下数量\n     * @property {Boolean}      fixed  - 列表项高度是否固定，默认为true\n     * @property {String}       clazz  - 列表项标识，默认为js-item\n     */\n    _p._$$ListHolder = _k._$klass();\n    _pro = _p._$$ListHolder._$extend(_t._$$EventTarget);\n    /**\n     * 控件初始化\n     *\n     * @protected \n     * @method module:util/list/holder._$$ListHolder#__init\n     * @return {Void}\n     */\n    _pro.__init = (function(){\n        var _style = {\n            height:0,\n            overflow:'hidden',\n            visibility:'hidden'\n        };\n        var _doInitHolder = function(_node){\n            _e._$style(_node,_style);\n        };\n        return function(){\n            // build placeholder\n            this.__holders = {\n                top:_e._$create('div'),\n                bottom:_e._$create('div')\n            };\n            _u._$loop(this.__holders,_doInitHolder);\n            this.__super();\n        };\n    })();\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/list/holder._$$ListHolder#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = (function(){\n        var _doResetHolder = function(_node){\n            _e._$setStyle(_node,'height',0);\n        };\n        return function(_options){\n            this.__super(_options);\n            this._$limit(_options.limit);\n            this.__clazz = _options.clazz||'js-item';\n            this.__fixed = _options.fixed;\n            if (this.__fixed==null){\n                this.__fixed = !0;\n            }\n            this.__sbody = _e._$get(_options.sbody);\n            this.__doInitDomEvent([[\n                this.__sbody,'scroll',\n                this.__doScrollCheck._$bind(this)\n            ]]);\n            this.__hbody = _e._$get(_options.hbody)||this.__sbody;\n            if (!!this.__hbody){\n                this.__fragments = {\n                    tlist:[],blist:[],\n                    top:document.createDocumentFragment(),\n                    bottom:document.createDocumentFragment()\n                };\n                _u._$loop(this.__holders,_doResetHolder);\n                this.__hbody.appendChild(this.__holders.bottom);\n                this.__hbody.insertAdjacentElement('afterBegin',this.__holders.top);\n            }\n            if (!!this.__sbody){\n                this.__doScrollCheck();\n            }\n        };\n    })();\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/list/holder._$$ListHolder#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        this._$clearHolder();\n        delete this.__fragments;\n        delete this.__clazz;\n        delete this.__fixed;\n        delete this.__limit;\n        delete this.__sbody;\n        delete this.__hbody;\n    };\n    /**\n     * 滚动检测\n     *\n     * @protected\n     * @method module:util/list/holder._$$ListHolder#__doScrollCheck\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__doScrollCheck = function(_event){\n        this._$check({\n            scrollTop:this.__sbody.scrollTop,\n            clientHeight:this.__sbody.clientHeight,\n            list:_e._$getByClassName(\n                this.__hbody,this.__clazz\n            )\n        });\n    };\n    /**\n     * 设置数量限制\n     *\n     * @method module:util/list/holder._$$ListHolder#_$limit\n     * @param  {Number|Array} arg0 - 限制数量\n     * @return {Void}\n     */\n    _pro._$limit = function(_limit){\n        if (!_u._$isArray(_limit)){\n            _limit = parseInt(_limit)||10;\n            _limit = [_limit,_limit];\n        }\n        this.__limit = _limit;\n    };\n    /**\n     * 检查列表情况\n     *\n     * @method   module:util/list/holder._$$ListHolder#_$check\n     * @param    {Object} arg0         - 滚动信息\n     * @property {Number} scrollTop    - 滚动高度\n     * @property {Number} clientHeight - 可视高度\n     * @property {Number} offset       - 初始项偏移量，不传根据滚动容器计算\n     * @property {Array}  list         - 待检查列表\n     * @return   {Void}\n     */\n    _pro._$check = (function(){\n        var _doCalOffset = function(){\n\n        };\n        return function(_info){\n            var _list = _info.list;\n            if (!_list||!_list.length) return;\n            var _ptr0,_ptr1,\n                _delta,_bottom,\n                _offset = _info.offset,\n                _stop = _info.scrollTop,\n                _sbtm = _stop+_info.clientHeight;\n            _u._$forIn(_list,function(_node,_index,_list){\n                // calculate offset of item\n                if (_offset==null){\n                    _offset = _e._$offset(_node,this.__sbody).y;\n                    if (this.__fixed){\n                        _delta = _node.offsetHeight;\n                    }\n                }else if(this.__fixed){\n                    _offset += _delta;\n                }else{\n                    _offset += _list[_index-1].offsetHeight;\n                }\n                // check item in top view\n                _bottom = _offset+(_delta!=null?_delta:_node.offsetHeight);\n                if (_ptr0==null&&_offset<=_stop&&_stop<=_bottom){\n                    _ptr0 = _index;\n                }\n                if(_ptr1==null&&_offset<=_sbtm&&_sbtm<=_bottom){\n                    _ptr1 = _index;\n                    return !0;\n                }\n                // check limit\n            },this);\n        };\n    })();\n    /**\n     * 清除占位符\n     * \n     * @method module:util/list/holder._$$ListHolder#_$clearHolder\n     * @return {Void}\n     */\n    _pro._$clearHolder = function(){\n        _u._$loop(\n            this.__holders,\n            _e._$removeByEC\n        );\n        if (!this.__hbody) return;\n        this.__hbody.appendChild(this.__fragments.bottom);\n        this.__hbody.insertAdjacentElement('afterBegin',this.__fragments.top);\n        delete this.__fragments.tlist;\n        delete this.__fragments.blist;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/list/module.js",
    "content": "/*\n * ------------------------------------------\n * 列表模块基类实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/list/module */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    'base/event',\n    'base/element',\n    'ui/item/list',\n    'ui/pager/pager',\n    'util/event',\n    'util/template/jst',\n    'util/template/tpl',\n    'util/cache/list'\n],function(NEJ,_k,_u,_v,_e,_i0,_i1,_t0,_t1,_t2,_t3,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 列表模块基类\n     *\n     * @class    module:util/list/module._$$ListModule\n     * @extends  module:util/event._$$EventTarget\n     *\n     * @param    {Object}        config - 可选配置参数\n     * @property {String|Node}   parent - 列表容器节点\n     * @property {Number}        limit  - 每页显示数量，默认10项\n     * @property {Number}        first  - 首页显示数量，默认为limit的值\n     * @property {String|Object} item   - 列表JST模版标识或者Item配置，{clazz:'xxx',klass:_$$Item||'jst key',prefix:'xxx'}\n     * @property {Object}        cache  - 缓存配置信息，{key:'primary key',lkey:'list key',data:{},ext:{},klass:_$$CacheList,list:[],clear:true,total:200}\n     * @property {Object}        pager  - 分页器配置信息，{parent:'xxx',klass:_$$Pager,index:2,fixed:true}\n     */\n    /**\n     * 下拉刷新列表之前处理业务逻辑，可用于处理loading状态的显示\n     * \n     * @event    module:util/list/module._$$ListModule#onbeforepullrefresh\n     * @param    {Object}  event   - 事件信息\n     * @property {Node}    parent  - 容器节点\n     * @property {String}  value   - 设置此参数返回用以显示loading的html代码或者节点\n     * @property {Boolean} stopped - 设置此参数用以表明loading已处理，后续逻辑忽略处理loading状态\n     */\n    /**\n     * 下拉刷新列表载入之后处理业务逻辑，可用于处理loading状态的隐藏\n     * \n     * @event    module:util/list/module._$$ListModule#onafterpullrefresh\n     * @param    {Object}  event   - 事件信息\n     * @property {Node}    parent  - 容器节点\n     * @property {String}  value   - 设置此参数返回用以显示loading的html代码\n     * @property {Boolean} stopped - 设置此参数用以表明loading已处理，后续逻辑忽略处理loading状态\n     */\n    /**\n     * 加载列表之前处理业务逻辑，可用于处理loading状态的显示\n     * \n     * @event    module:util/list/module._$$ListModule#onbeforelistload\n     * @param    {Object}  event   - 事件信息\n     * @property {Node}    parent  - 容器节点\n     * @property {String}  value   - 设置此参数返回用以显示loading的html代码或者节点\n     * @property {Boolean} stopped - 设置此参数用以表明loading已处理，后续逻辑忽略处理loading状态\n     */\n    /**\n     * 列表载入之后处理业务逻辑，可用于处理loading状态的隐藏\n     * \n     * @event    module:util/list/module._$$ListModule#onafterlistload\n     * @param    {Object}  event   - 事件信息\n     * @property {Node}    parent  - 容器节点\n     * @property {String}  value   - 设置此参数返回用以显示loading的html代码\n     * @property {Boolean} stopped - 设置此参数用以表明loading已处理，后续逻辑忽略处理loading状态\n     */\n    /**\n     * 为空列表时显示的信息\n     * \n     * @event    module:util/list/module._$$ListModule#onemptylist\n     * @param    {Object}  event   - 事件信息\n     * @property {Node}    parent  - 容器节点\n     * @property {String}  value   - 设置此参数返回用以显示的html代码\n     * @property {Boolean} stopped - 设置此参数用以表明已处理，后续逻辑忽略处理状态\n     */\n    /**\n     * 页码变化触发事件\n     * \n     * @event    module:util/list/module._$$ListModule#onpagechange\n     * @param    {Object}  event   - 事件信息\n     * @property {Number}  index   - 当前页码\n     * @property {Boolean} stopped - 设置此参数用以表明已处理，后续逻辑忽略分页处理\n     */\n    /**\n     * 列表显示之前处理业务逻辑，此事件确保列表有数据\n     * \n     * @event    module:util/list/module._$$ListModule#onbeforelistrender\n     * @param    {Object} event  - 事件信息\n     * @property {Node}   parent - 容器节点\n     * @property {Number} offset - 当前绘制列表偏移量\n     * @property {Number} limit  - 当前绘制列表数量\n     * @property {Number} total  - 当前列表总数\n     * @property {Array}  list   - 当前列表\n     */\n    /**\n     * 列表显示之后处理业务逻辑，此事件确保列表有数据\n     * \n     * @event    module:util/list/module._$$ListModule#onafterlistrender\n     * @param    {Object} event  - 事件信息\n     * @property {Node}   parent - 容器节点\n     * @property {Number} offset - 当前绘制列表偏移量\n     * @property {Number} limit  - 当前绘制列表数量\n     * @property {Number} total  - 当前列表总数\n     * @property {Array}  list   - 当前列表\n     */\n    /**\n     * 列表清除之前处理业务逻辑\n     * \n     * @event    module:util/list/module._$$ListModule#onbeforelistclear\n     * @param    {Object} event  - 事件信息\n     * @property {Node}   parent - 容器节点\n     */\n    /**\n     * 请求更新列表项数据，主要用于处理删除之前的确认，\n     * 确认完成后可调用模块的_$delete接口将数据从服务器上删除\n     * \n     * @event  module:util/list/module._$$ListModule#ondelete\n     * @param  {Object} event - 列表项数据\n     */\n    /**\n     * 删除列表项之前回调，主要用来预处理调用Cache中的删除接口时的信息\n     * \n     * @event    module:util/list/module._$$ListModule#onbeforedelete\n     * @param    {Object} event - 事件信息\n     * @property {String} id    - 列表项标识\n     * @property {String} key   - 列表标识\n     * @property {Object} data  - 列表项数据\n     */\n    /**\n     * 删除列表项之后回调，主要用来额外处理列表呈现的业务逻辑\n     * \n     * @event    module:util/list/module._$$ListModule#onafterdelete\n     * @param    {Object}  event   - 事件信息\n     * @property {String}  key     - 列表标识\n     * @property {Object}  data    - 删除的列表项数据\n     * @property {Boolean} stopped - 是否阻止列表刷新逻辑\n     */\n    /**\n     * 请求更新列表项数据，针对JST模版的用户点击行为，\n     * 主要用于处理收集更新数据，更新数据收集完成后可调用模块的_$update接口将数据更新到服务器\n     * \n     * @event  module:util/list/module._$$ListModule#onupdate\n     * @param  {Object} event - 列表项数据\n     */\n    /**\n     * 更新列表项之前回调，主要用来预处理调用Cache中的更新接口时的信息\n     * \n     * @event    module:util/list/module._$$ListModule#onbeforeupdate\n     * @param    {Object} event - 事件信息\n     * @property {String} id    - 列表项标识\n     * @property {String} key   - 列表标识\n     * @property {Object} data  - 列表项数据\n     */\n    /**\n     * 更新列表项之后回调，主要用来额外处理列表呈现的业务逻辑\n     * \n     * @event    module:util/list/module._$$ListModule#onafterupdate\n     * @param    {Object}  event   - 事件信息\n     * @property {String}  key     - 列表标识\n     * @property {Object}  data    - 删除的列表项数据\n     * @property {Boolean} stopped - 是否阻止列表刷新逻辑\n     */\n    /**\n     * 错误处理回调\n     * \n     * @event  module:util/list/module._$$ListModule#onerror\n     */\n    _p._$$ListModule = _k._$klass();\n    _pro = _p._$$ListModule._$extend(_t0._$$EventTarget);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/list/module._$$ListModule#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__ropt = {};\n        this.__super(_options);\n        this.__lbox = _e._$get(_options.parent);\n        this.__iopt = {parent:this.__lbox};\n        this.__limit = parseInt(_options.limit)||10;\n        this.__first = parseInt(_options.first)||this.__limit;\n        this.__doResetTemplate(_options.item);\n        this.__doResetCache(_options.cache||_o);\n        this.__doResetPager(_options.pager||_o);\n        this._$refresh();\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/list/module._$$ListModule#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this._$dispatchEvent('onbeforerecycle');\n        this.__doClearListBox();\n        this.__super();\n        if (this.__ropt.clear){\n            this.__cache._$clearListInCache(this.__ropt.key);\n        }\n        this.__cache._$recycle();\n        if (!!this.__pager){\n            this.__pager._$recycle();\n            delete this.__pager;\n        }\n        delete this.__pkls;\n        delete this.__popt;\n        delete this.__pulling;\n        delete this.__cache;\n        delete this.__lbox;\n        delete this.__ikls;\n        delete this.__iopt;\n        delete this.__iext;\n        delete this.__ropt;\n    };\n    /**\n     * 根据数据ID取项节点ID\n     * \n     * @protected\n     * @method module:util/list/module._$$ListModule#__getItemBodyId\n     * @param  {String} 数据ID\n     * @return {String} 节点ID\n     */\n    _pro.__getItemBodyId = function(_id){\n        return this.__getItemId(_id)+\n               _t1._$seed();\n    };\n    /**\n     * 取项标识\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__getItemId\n     * @param  {String} arg0 - 数据标识\n     * @return {String}        项标识\n     */\n    _pro.__getItemId = function(_id){\n        var _prefix = (this.__iopt||_o).prefix||'';\n        return _prefix+_id;\n    };\n    /**\n     * 取当前偏移量的分页信息\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__getPageInfo\n     * @param  {Number} arg0 - 偏移位置\n     * @param  {Number} arg1 - 长度\n     * @return {Object}        分页信息，如：{index:1,total:4}\n     */\n    _pro.__getPageInfo = function(_point,_offset,_limit,_length){\n        var _result = {\n            index:1,\n            total:1\n        };\n        if (_offset>=_point){\n            _result.index = Math.floor((_offset-_point)/_limit)+2;\n        }\n        if (_length>_point){\n            _result.total = Math.ceil((_length-_point)/_limit)+1;\n        }\n        return _result;\n    };\n    /**\n     * 重置JST模版\n     * \n     * @protected\n     * @method module:util/list/module._$$ListModule#__doResetJSTTemplate\n     * @param  {String} arg0 - JST标识\n     * @return {Void}\n     */\n    _pro.__doResetJSTTemplate = function(_key){\n        delete this.__ikls;\n        this.__ikey = _key;\n        this.__doInitDomEvent([[\n            this.__lbox,'click',\n            this.__onCheckAction._$bind(this)\n        ]]);\n    };\n    /**\n     * 重置列表项模版配置\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__doResetTemplate\n     * @param  {String|Object} arg0 - 列表项模版配置\n     * @return {Void}\n     */\n    _pro.__doResetTemplate = function(_item){\n        // if item is jst-key\n        if (_u._$isString(_item)){\n            this.__doResetJSTTemplate(_item);\n            return;\n        }\n        // if item is jst with options\n        _u._$merge(this.__iopt,_item);\n        // filter jst extend function\n        this.__iext = _u._$merge(\n            {},_item,function(_it){\n                return !_u._$isFunction(_it);\n            }\n        );\n        var _klass = this.__iopt.klass;\n        delete this.__iopt.klass;\n        if (_u._$isString(_klass)){\n            this.__doResetJSTTemplate(_klass);\n            return;\n        }\n        // if item is Item template\n        delete this.__ikey;\n        this.__ikls = _klass;\n        this.__iopt.ondelete = this\n            ._$dispatchEvent._$bind(this,'ondelete');\n        this.__iopt.onupdate = this\n            ._$dispatchEvent._$bind(this,'onupdate');\n    };\n    /**\n     * 重置缓存信息配置\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__doResetCache\n     * @param  {Object} arg0 - 缓存配置\n     * @return {Void}\n     */\n    _pro.__doResetCache = function(_cache){\n        var _klass = _cache.klass,\n            _copt  = _u._$merge({},_cache);\n        this.__ropt.key = _copt.lkey;\n        this.__ropt.ext = _copt.ext;\n        this.__ropt.data = _copt.data||{};\n        this.__ropt.clear = !!_copt.clear;\n        this.__iopt.pkey = _copt.key||'id';\n        _copt.onerror = \n            this._$dispatchEvent._$bind(this,'onerror');\n        _copt.onlistload =\n            this.__cbListLoad._$bind(this);\n        _copt.onpullrefresh =\n            this.__cbPullRefresh._$bind(this);\n        if (!!_klass&&('onlistchange' in _klass)){\n            this.__doInitDomEvent([[\n                _klass,'listchange',\n                this.__cbListChange._$bind(this)\n            ]]);\n        }else{\n            _copt.onitemadd = this.\n                __cbItemAdd._$bind(this);\n            _copt.onitemdelete = this.\n                __cbItemDelete._$bind(this);\n            _copt.onitemupdate = this.\n                __cbItemUpdate._$bind(this);\n        }\n        this.__cache = (_klass||_t3._$$CacheList)._$allocate(_copt);\n        // set total\n        if (_cache.total!=null){\n            this.__cache._$setTotal(\n                this.__ropt.key,\n                _cache.total\n            );\n        }\n        // set list\n        if (!!_cache.list){\n            this.__cache._$setListInCache(\n                this.__ropt.key,\n                _cache.list\n            );\n        }\n    };\n    /**\n     * 重置分页器配置\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__doResetPager\n     * @param  {Object} 分页器配置\n     * @return {Void}\n     */\n    _pro.__doResetPager = function(_pager){\n        this.__pkls = _pager.klass||_i1._$$Pager;\n        this.__popt = _u._$merge({},_pager);\n        // parse bind pager\n        if (_u._$isArray(_pager.parent)){\n            this.__popt.parent = _pager.parent[0];\n            this.__pbid = _pager.parent.slice(1);\n            if (!this.__pbid||!this.__pbid.length){\n                delete this.__pbid;\n            }\n        }\n        delete this.__popt.klass;\n    };\n    /**\n     * 清理列表容器\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__doClearListBox\n     * @return {Void}\n     */\n    _pro.__doClearListBox = (function(){\n        var _reg0 = /^(?:table|tr|tbody|ul|ol|select)$/i;\n        return function(){\n            this._$dispatchEvent('onbeforelistclear',{\n                parent:this.__lbox\n            });\n            if (!!this.__items&&this.__items.length>0){\n                this.__items = this.__ikls\n                    ._$recycle(this.__items);\n                delete this.__items;\n            }\n            if (_reg0.test(this.__lbox.tagName)){\n                _e._$clearChildren(this.__lbox);\n            }else{\n                this.__lbox.innerHTML = '';\n            }\n        };\n    })();\n    /**\n     * 切换分页器的显示状态\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__doSwitchPagerShow\n     * @return {Void}\n     */\n    _pro.__doSwitchPagerShow = function(_display){\n        if (!!this.__popt.fixed) return;\n        _e._$setStyle(this.__popt.parent,'display',_display);\n        _u._$forEach(\n            this.__pbid,function(_parent){\n                _e._$setStyle(_parent,'display',_display);\n            },this\n        );\n    };\n    /**\n     * 通过分页器刷新当前页\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__doRefreshByPager\n     * @return {Void}\n     */\n    _pro.__doRefreshByPager = function(){\n        var _index = this.__popt.index||1;\n        delete this.__popt.index;\n        if (!!this.__pager){\n            _index = this.__pager._$getIndex();\n        }\n        this.__doChangePage({\n            last:_index,\n            index:_index\n        });\n    };\n    /**\n     * 页码变化处理逻辑\n     * \n     * @protected\n     * @method module:util/list/module._$$ListModule#__doChangePage\n     * @param  {Object} arg0 - 页码信息\n     * @return {Void}\n     */\n    _pro.__doChangePage = function(_event){\n        this._$dispatchEvent('onpagechange',_event);\n    };\n    /**\n     * 偏移量变化处理逻辑\n     * \n     * @protected\n     * @method module:util/list/module._$$ListModule#__doChangeOffset\n     * @param  {Number} arg0 - 偏移量\n     * @return {Void}\n     */\n    _pro.__doChangeOffset = function(_offset){\n        this.__ropt.offset = _offset;\n        this.__doBeforeListLoad();\n        this.__doLoadList();\n    };\n    /**\n     * 生成请求对象信息\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__doGenRequestOpt\n     * @param  {Object} arg0 - 预处理请求信息\n     * @return {Object}        处理后请求信息\n     */\n    _pro.__doGenRequestOpt = function(_options){\n        return _options;\n    };\n    /**\n     * 加载数据列表\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__doLoadList\n     * @return {Void}\n     */\n    _pro.__doLoadList = function(){\n        // load data from cache\n        var _data = this.__ropt.data;\n        _data.offset = this.__ropt.offset;\n        var _first = _data.offset==0;\n        _data.total  = _first;\n        this.__ropt.limit =\n              _first?this.__first:this.__limit;\n        _data.limit  = this.__ropt.limit;\n        this.__cache._$getList(\n            this.__doGenRequestOpt(\n                _u._$merge({},this.__ropt)\n            )\n        );\n    };\n    /**\n     * 数据列表载入完成回调\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__cbListLoad\n     * @param  {Object} arg0 - 请求信息\n     * @return {Void}\n     */\n    _pro.__cbListLoad = function(_options){\n        if (_options.key!=this.__ropt.key||\n            _options.offset!=this.__ropt.offset) return;\n        //console.log('list load -> '+_options.key);\n        this.__doBeforeListShow();\n        // check list\n        var _list = this.__cache.\n            _$getListInCache(_options.key);\n        if (!_list||!_list.length){\n            // check load error\n            if (!this._$cache()._$isLoaded(_options.key)){\n                this.__doShowMessage('onlistloaderror','列表加载失败');\n                //this._$dispatchEvent('onlistloaderror',{\n                //    parent:this.__lbox\n                //});\n            }else{\n                this.__doShowEmpty();\n            }\n            return !0;\n        }\n        // render list\n        var _limit = _options.limit,\n            _offset = _options.offset;\n        if (!this.__cache._$isFragmentFilled(_options.key,_offset,_limit)){\n            this.__doShowMessage('onlistloaderror','列表加载失败');\n            //this._$dispatchEvent('onlistloaderror',{\n            //    parent:this.__lbox\n            //});\n            return !0;\n        }\n        if (this.__doBeforeListRender(\n                  _list,_offset,_limit))\n            return;\n        this._$dispatchEvent('onbeforelistrender',{\n            list:_list,\n            limit:_limit,\n            offset:_offset,\n            parent:this.__lbox,\n            total:this.__cache._$getTotal(_options.key)\n        });\n        if (!!this.__ikey){\n            // render by jst\n            this.__iopt.xlist = _list;\n            this.__iopt.beg = _offset;\n            this.__iopt.end = Math.min(_list.length,_offset+_limit)-1;\n            this.__iopt.act = 'list';\n            var _html = _t1._$get(\n                this.__ikey,\n                this.__iopt,\n                this.__iext\n            );\n            this.__doShowListByJST(_html);\n        }else{\n            // render by item\n            this.__iopt.limit = _limit;\n            this.__iopt.offset = _offset;\n            var _items = _t2._$getItemTemplate(\n                         _list,this.__ikls,this.__iopt);\n            this.__doShowListByItem(_items);\n        }\n        this._$dispatchEvent('onafterlistrender',{\n            list:_list,\n            limit:_limit,\n            offset:_offset,\n            parent:this.__lbox,\n            total:this.__cache._$getTotal(_options.key)\n        });\n    };\n    /**\n     * 前向刷新数据列表载入完成回调\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__cbPullRefresh\n     * @param  {Object} arg0 - 请求信息\n     * @return {Void}\n     */\n    _pro.__cbPullRefresh = function(_options){\n        // unlock pulling\n        if (!this.__pulling)\n            return;\n        delete this.__pulling;\n        // recycle loading\n        this.__doBeforeListShow('onafterpullrefresh');\n        this._$refresh();\n    };\n    /**\n     * 同步分页器\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__doSyncPager\n     * @param  {Number}  arg0 - 页码索引\n     * @param  {Number}  arg1 - 总页数\n     * @return {Boolean}        是否重置页码\n     */\n    _pro.__doSyncPager = function(_index,_total){\n        if (!!this.__pager){\n            // limit page total\n            if ((this.__popt||_o).limit>0){\n                _total = Math.min(\n                    _total,this.__popt.limit\n                );\n            }\n            // check pager index and total\n            var _index2 = this.__pager._$getIndex(),\n                _total2 = this.__pager._$getTotal();\n            if (_index2>_total||_total!=_total2){\n                this.__pager._$recycle();\n                delete this.__pager;\n                this.__doChangePage({\n                    last:_index2,\n                    index:Math.min(_index,_total)\n                });\n                return !0;\n            }\n        }else{\n            // check pager instance\n            this.__popt.index = _index;\n            this.__popt.total = _total;\n            this.__pager = this.__pkls._$allocate(this.__popt);\n            this.__pager._$setEvent('onchange',this.__doChangePage._$bind(this));\n            _u._$forEach(\n                this.__pbid,function(_parent){\n                    this.__pager._$bind(_parent);\n                },this\n            );\n        }\n    };\n    /**\n     * 格式化数据\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__doFormatData\n     * @param  {Object} arg0 - 数据信息\n     * @return {Void}\n     */\n    _pro.__doFormatData = (function(){\n        var _seed = +new Date;\n        return function(_data){\n            var _id = _data[this.__iopt.pkey];\n            if (!_id){\n                _data['dirty-data'] = !0;\n                _data[this.__iopt.pkey] = 'dirty-'+_seed++;\n            }\n            return _data;\n        };\n    })();\n    /**\n     * 分离脏数据\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__doSplitDirty\n     * @param  {Object} arg0 - 数据信息\n     * @return {String}        数据标识\n     */\n    _pro.__doSplitDirty = function(_data){\n        var _id = _data[this.__iopt.pkey];\n        if (!!_data['dirty-data']){\n            delete _data['dirty-data'];\n            delete _data[this.__iopt.pkey];\n        }\n        return _id;\n    };\n    /**\n     * 插入单项\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__doInsertOneItem\n     * @param  {String} arg0 - 插入位置\n     * @param  {Object} arg1 - 数据对象\n     * @return {Void}\n     */\n    _pro.__doInsertOneItem = (function(){\n        var _doInsert = function(_pos,_body){\n            this.__lbox.insertAdjacentElement(_pos,_body);\n        };\n        return function(_pos,_data){\n            var _xlist = [_data];\n            if (!!this.__ikey){\n                // render by jst\n                var _xlist = this.__cache._$getListInCache(\n                        this.__ropt.key\n                    ),\n                    _index = _u._$indexOf(_xlist,_data);\n                if (_index<0){\n                    _index = 0;\n                    _xlist = [_data];\n                }\n                this.__iopt.xlist = _xlist;\n                this.__iopt.beg = _index;\n                this.__iopt.end = _index;\n                this.__iopt.act = 'add';\n                this.__doShowListByJST(\n                    _t1._$get(\n                        this.__ikey,\n                        this.__iopt,\n                        this.__iext\n                    ),_pos\n                );\n            }else{\n                // render by item\n                this.__iopt.limit = 1;\n                this.__iopt.offset = 0;\n                this.__iopt.parent =\n                      _doInsert._$bind(this,_pos);\n                var _items = _t2._$getItemTemplate(\n                             _xlist,this.__ikls,this.__iopt);\n                this.__iopt.parent = this.__lbox;\n                this.__doShowListByItem(_items);\n            }\n            this._$dispatchEvent('onafterinsert');\n        };\n    })();\n    /**\n     * 加载数据之前处理逻辑，子类实现具体业务逻辑\n     * \n     * @abstract\n     * @method module:util/list/module._$$ListModule#__doBeforeListLoad\n     * @return {Void}\n     */\n    _pro.__doBeforeListLoad = _f;\n    /**\n     * 数据载入之后处理逻辑，子类实现具体业务逻辑\n     * \n     * @abstract\n     * @method module:util/list/module._$$ListModule#__doBeforeListShow\n     * @return {Void}\n     */\n    _pro.__doBeforeListShow = function(_name){\n        var _event = {\n            parent:this.__lbox\n        };\n        this._$dispatchEvent(_name||'onafterlistload',_event);\n        if (!_event.stopped){\n            _e._$removeByEC(this.__ntip);\n        }\n    };\n    /**\n     * 列表绘制之前处理逻辑，子类实现具体业务逻辑\n     * \n     * @abstract\n     * @method module:util/list/module._$$ListModule#__doBeforeListRender\n     * @return {Void}\n     */\n    _pro.__doBeforeListRender = _f;\n    /**\n     * 呈现提示信息\n     * \n     * @protected\n     * @method module:util/list/module._$$ListModule#__doRenderMessage\n     * @param  {String} arg0 - 消息内容\n     * @param  {String} arg1 - 位置信息\n     * @return {Void}\n     */\n    _pro.__doRenderMessage = function(_message,_pos){\n        if (_u._$isString(_message)){\n            if (!this.__ntip)\n                 this.__ntip = _e._$create('div');\n            this.__ntip.innerHTML = _message;\n        }else{\n            this.__ntip = _message;\n        }\n        this.__lbox.insertAdjacentElement(\n            _pos||'beforeEnd',this.__ntip\n        );\n    };\n    /**\n     * 通过事件回调检测显示信息\n     * \n     * @protected\n     * @method module:util/list/module._$$ListModule#__doShowMessage\n     * @param  {String} arg0 - 事件名称\n     * @param  {String} arg1 - 默认显示内容\n     * @return {Void}\n     */\n    _pro.__doShowMessage = function(_name,_default,_pos){\n        var _event = {\n            parent:this.__lbox\n        };\n        if (!!_name){\n            this._$dispatchEvent(_name,_event);\n        }\n        if (!_event.stopped){\n            this.__doRenderMessage(\n                _event.value||_default,_pos\n            );\n        }\n    };\n    /**\n     * 列表为空时处理逻辑，子类实现具体业务逻辑\n     * \n     * @abstract\n     * @method module:util/list/module._$$ListModule#__doShowEmpty\n     * @return {Void}\n     */\n    _pro.__doShowEmpty = _f;\n    /**\n     * 以jst模版方式绘制列表，子类实现具体业务逻辑\n     * \n     * @abstract\n     * @method module:util/list/module._$$ListModule#__doShowListByJST\n     * @return {Void}\n     */\n    _pro.__doShowListByJST = _f;\n    /**\n     * 以item模版方式绘制列表，子类实现具体业务逻辑\n     * \n     * @abstract\n     * @method module:util/list/module._$$ListModule#__doShowListByItem\n     * @return {Void}\n     */\n    _pro.__doShowListByItem = _f;\n    /**\n     * 检查列表行为\n     *\n     * @protected\n     * @method module:util/list/module._$$ListModule#__onCheckAction\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onCheckAction = (function(){\n        var _reg0 = /^(?:delete|update)$/;\n        return function(_event){\n            var _node = _v._$getElement(_event,'d:action');\n            if (!_node) return;\n            var _action = _e._$dataset(_node,'action');\n            if (!_reg0.test(_action)) return;\n            var _id = _e._$dataset(_node,'id');\n            if (!_id) return;\n            var _item = this.__cache._$getItemInCache(_id);\n            if (!_item) return;\n            _v._$stop(_event);\n            this._$dispatchEvent('on'+_action,{\n                data:_item,\n                id:_item[this.__iopt.pkey],\n                body:_e._$get(this.__getItemBodyId(_id))\n            });\n        };\n    })();\n    /**\n     * 添加列表项回调，子类按需实现具体业务逻辑\n     * \n     * @abstract\n     * @method module:util/list/module._$$ListModule#__cbItemAdd\n     * @return {Void}\n     */\n    _pro.__cbItemAdd = _f;\n    /**\n     * 删除列表项\n     * \n     * @protected\n     * @method   module:util/list/module._$$ListModule#__doDeleteItem\n     * @param    {Object} arg0 - 列表项信息\n     * @property {String} id   - 项标识\n     * @property {Object} data - 项绑定的数据信息\n     * @return   {Void}\n     */\n    _pro.__doDeleteItem = function(_event){\n        var _data = _event.data||{},\n            _options = {\n                data:_data,\n                key:this.__ropt.key,\n                id:_data[this.__iopt.pkey]\n            };\n        this._$dispatchEvent('onbeforedelete',_options);\n        this.__cache._$deleteItem(_options);\n    };\n    /**\n     * 删除列表项回调，子类按需实现具体业务逻辑\n     * \n     * @abstract\n     * @method module:util/list/module._$$ListModule#__cbItemDelete\n     * @return {Void}\n     */\n    _pro.__cbItemDelete = _f;\n    /**\n     * 更新列表项\n     * \n     * @protected\n     * @method   module:util/list/module._$$ListModule#__doUpdateItem\n     * @param    {Object} arg0 - 列表项信息\n     * @property {String} id   - 项标识\n     * @property {Object} data - 项绑定的数据信息\n     * @return   {Void}\n     */\n    _pro.__doUpdateItem = function(_event){\n        var _data = _event.data||{},\n            _options = {\n                data:_data,\n                key:this.__ropt.key\n            };\n        this._$dispatchEvent('onbeforeupdate',_options);\n        this.__cache._$updateItem(_options);\n    };\n    /**\n     * 更新列表项回调，子类可按需重写具体业务逻辑\n     * \n     * @protected\n     * @method module:util/list/module._$$ListModule#__cbItemUpdate\n     * @return {Void}\n     */\n    _pro.__cbItemUpdate = function(_event){\n        this.__doCheckResult(_event,'onafterupdate');\n        if (_event.stopped) return;\n        var _id = _event.data[this.__iopt.pkey];\n        if (!!this.__items){\n            var _item = _t2._$getItemById(\n                this.__getItemId(_id)\n            );\n            if (!!_item) _item._$refresh(_event.data);\n        }else{\n            var _node = this._$getItemBody(_id);\n            if (!_node) return;\n            var _list = this.__cache._$getListInCache(this.__ropt.key),\n                _index = _u._$indexOf(_list,_event.data);\n            if (_index<0) return;\n            this.__iopt.xlist = _list;\n            this.__iopt.beg  = _index;\n            this.__iopt.end  = _index;\n            this.__iopt.act  = 'update';\n            var _html = _t1._$get(\n                this.__ikey,\n                this.__iopt,\n                this.__iext\n            );\n            _node.insertAdjacentHTML('afterEnd',_html);\n            _e._$remove(_node);\n        }\n        this._$dispatchEvent('onafterupdaterender',{\n            data:_event.data,\n            parent:this.__lbox\n        });\n    };\n    /**\n     * 验证操作结果\n     * \n     * @protected\n     * @method module:util/list/module._$$ListModule#__doCheckResult\n     * @param  {Object} arg0 - 事件信息\n     * @return {Void}\n     */\n    _pro.__doCheckResult = function(_event,_name){\n        var _item = _event.data;\n        if (!_item||_item[this.__iopt.pkey]==null){\n            this._$dispatchEvent('onerror',_event);\n            _event.stopped = !0;\n        }\n        if (!_event.stopped){\n            this._$dispatchEvent(_name,_event);\n        }\n    };\n    /**\n     * 追加数据片段回调\n     *\n     * @abstract\n     * @method module:util/list/module._$$ListModule#__cbAppendList\n     * @param  {Number} arg0 - 偏移量\n     * @param  {Number} arg1 - 数量\n     * @return {Void}\n     */\n    _pro.__cbAppendList = _f;\n    /**\n     * 前向追加数据片段回调\n     *\n     * @abstract\n     * @method module:util/list/module._$$ListModule#__cbUnshiftList\n     * @param  {Number} arg0 - 偏移量\n     * @param  {Number} arg1 - 数量\n     * @return {Void}\n     */\n    _pro.__cbUnshiftList = _f;\n    /**\n     * 列表变化回调（删除/添加），子类按需实现具体业务逻辑\n     * \n     * @protected\n     * @method module:util/list/module._$$ListModule#__cbListChange\n     * @return {Void}\n     */\n    _pro.__cbListChange = function(_event){\n        if (!!_event.key&&\n            _event.key!=this.__ropt.key){\n            return;\n        }\n        switch(_event.action){\n            case 'add':\n                this.__cbItemAdd(_event);\n            break;\n            case 'delete':\n                this.__cbItemDelete(_event);\n            break;\n            case 'update':\n                this.__cbItemUpdate(_event);\n            break;\n            case 'refresh':\n                this._$refresh();\n            break;\n            case 'unshift':\n                this.__cbUnshiftList(\n                    _event.offset,\n                    _event.limit\n                );\n            break;\n            case 'append':\n                this.__cbAppendList(\n                    _event.offset,\n                    _event.limit\n                );\n            break;\n        }\n    };\n    /**\n     * 更新某一项数据\n     * \n     * @method module:util/list/module._$$ListModule#_$update\n     * @param  {Object} arg0 - 需要更新的数据\n     * @return {Void}\n     */\n    _pro._$update = function(_item){\n        this.__doUpdateItem({data:_item});\n    };\n    /**\n     * 删除某一项数据\n     * \n     * @method module:util/list/module._$$ListModule#_$delete\n     * @param  {Object} arg0 - 需要删除的数据\n     * @return {Void}\n     */\n    _pro._$delete = function(_item){\n        this.__doDeleteItem({data:_item});\n    };\n    /**\n     * 添加一项数据\n     * \n     * @method module:util/list/module._$$ListModule#_$add\n     * @param  {Object} arg0 - 需要添加的数据\n     * @return {Void}\n     */\n    _pro._$add = function(_item){\n        this.__cache._$addItem({\n            data:_item,\n            key:this.__ropt.key\n        });\n    };\n    /**\n     * 取缓存实例\n     * \n     * @method module:util/list/module._$$ListModule#_$cache\n     * @return {module:util/cache/list._$$CacheList} 列表缓存实例\n     */\n    _pro._$cache = function(){\n        return this.__cache;\n    };\n    /**\n     * 往前追加列表项\n     *\n     * @method module:util/list/module._$$ListModule#_$unshift\n     * @param  {Object} arg0 - 数据信息\n     * @return {Number}        插入项标识\n     */\n    _pro._$unshift = function(_data){\n        this.__doInsertOneItem(\n            'afterBegin',\n            this.__doFormatData(_data)\n        );\n        return this.__doSplitDirty(_data);\n    };\n    /**\n     * 往后追加列表项\n     *\n     * @method module:util/list/module._$$ListModule#_$append\n     * @param  {Object} arg0 - 数据信息\n     * @return {Number}        插入项标识\n     */\n    _pro._$append = function(_data){\n        this.__doInsertOneItem(\n            'beforeEnd',\n            this.__doFormatData(_data)\n        );\n        return this.__doSplitDirty(_data);\n    };\n    /**\n     * 刷新模块\n     * \n     * @method module:util/list/module._$$ListModule#_$refresh\n     * @param  {Number} arg0 - 刷新到的页码\n     * @return {Void}\n     */\n    _pro._$refresh = function(){\n        this.__doClearListBox();\n        this.__doRefreshByPager();\n    };\n    /**\n     * 先清数据再刷新模块\n     * \n     * @method module:util/list/module._$$ListModule#_$refreshWithClear\n     * @return {Void}\n     */\n    _pro._$refreshWithClear = function(){\n        this.__cache._$clearListInCache(this.__ropt.key);\n        this._$refresh();\n    };\n    /**\n     * 重新加载列表\n     *\n     * @method module:util/list/module._$$ListModule#_$reload\n     * @param  {Boolean} arg0 - 是否清除缓存数据\n     * @return {Void}\n     */\n    _pro._$reload = function(noclear){\n        if (!noclear){\n            this.__cache._$clearListInCache(this.__ropt.key);\n        }\n        this.__doLoadList();\n    };\n    /**\n     * 前向刷新列表\n     * \n     * @method module:util/list/module._$$ListModule#_$pullRefresh\n     * @return {Void}\n     */\n    _pro._$pullRefresh = function(){\n        // lock pulling\n        if (!!this.__pulling)\n            return;\n        this.__pulling = !0;\n        // show loading\n        this.__doShowMessage(\n            'onbeforepullrefresh',\n            '列表刷新中...','afterBegin'\n        );\n        // refresh data\n        this.__cache._$pullRefresh({\n            key:this.__ropt.key,\n            data:this.__ropt.data\n        });\n    };\n    /**\n     * 取列表总数\n     *\n     * @method module:util/list/module._$$ListModule#_$getTotal\n     * @return {Number} 列表总数\n     */\n    _pro._$getTotal = function(){\n        return this.__cache._$getTotal(this.__ropt.key);\n    };\n    /**\n     * 取分页器实例\n     *\n     * @method module:util/list/module._$$ListModule#_$getPager\n     * @return {Void}\n     */\n    _pro._$getPager = function(){\n        return this.__pager;\n    };\n    /**\n     * 取ITEM列表\n     *\n     * @method module:util/list/module._$$ListModule#_$items\n     * @return {Array} ITEM列表\n     */\n    _pro._$items = function(){\n        return this.__items;\n    };\n    /**\n     * 取列表项节点\n     *\n     * @method module:util/list/module._$$ListModule#_$getItemBody\n     * @param  {String} arg0 - 数据标识\n     * @return {Node}          节点\n     */\n    _pro._$getItemBody = function(_id){\n        if (!!this.__ikey){\n            // render by jst\n            return _e._$get(\n                this.__getItemBodyId(_id)\n            );\n        }else{\n            // render by item\n            var _item = _t2._$getItemById(\n                this.__getItemId(_id)\n            );\n            if (!!_item){\n                return _item._$getBody();\n            }\n        }\n    };\n    /**\n     * 判断列表是否载入完成\n     *\n     * @method module:util/list/module._$$ListModule#_$isLoaded\n     * @return {Boolean}\n     */\n    _pro._$isLoaded = function(){\n        return this.__cache._$isLoaded(this.__ropt.key);\n    };\n    /**\n     * 显示信息\n     *\n     * @method module:util/list/module._$$ListModule#_$showMessage\n     * @param  {String|Node} arg0 - 消息内容\n     * @return {Void}\n     */\n    _pro._$showMessage = function(_html){\n        this.__doClearListBox();\n        this.__doShowMessage(null,_html);\n    };\n    /**\n     * 去到下一页列表\n     *\n     * @method module:util/list/module._$$ListModule#_$nextPage\n     * @return {Boolean} 是否还有下一页\n     */\n    _pro._$nextPage = function(){\n        if (!this.__pager){\n            return;\n        }\n        var _index = this.__pager._$getIndex()+1,\n            _total = this.__pager._$getTotal();\n        _index = Math.max(1,Math.min(_index,_total));\n        this._$pageTo(_index);\n        return _index<_total;\n    };\n    /**\n     * 去到上一页列表\n     *\n     * @method module:util/list/module._$$ListModule#_$nextPage\n     * @return {Boolean} 是否还有上一页\n     */\n    _pro._$prevPage = function(){\n        if (!this.__pager){\n            return;\n        }\n        var _index = this.__pager._$getIndex()-1,\n            _total = this.__pager._$getTotal();\n        _index = Math.max(1,Math.min(_index,_total));\n        this._$pageTo(_index);\n        return _index<=1;\n    };\n    /**\n     * 去到指定页码列表\n     *\n     * @method module:util/list/module._$$ListModule#_$pageTo\n     * @param  {Number} arg0 - 指定页码\n     * @return {Void}\n     */\n    _pro._$pageTo = function(_index){\n        if (!this.__pager){\n            return;\n        }\n        var _total = this.__pager._$getTotal();\n        _index = Math.max(1,Math.min(_index,_total));\n        this.__pager._$setIndex(_index);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/list/module.pager.js",
    "content": "// link to util/list/page for compatible\n// use util/list/page for new project\nNEJ.define(['./page.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/list/module.waterfall.js",
    "content": "// link to util/list/waterfall for compatible\n// use util/list/waterfall for new project\nNEJ.define(['./waterfall.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/list/page.js",
    "content": "/*\n * ------------------------------------------\n * 分页式列表模块实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/list/page */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    './module.js'\n],function(NEJ,_k,_u,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 分页式列表模块\n     * \n     * 结构举例\n     * ```html\n     * <div class=\"mbox\">\n     *   <div class=\"lbox\" id=\"list-box\">\n     *     <!-- list box -->\n     *   </div>\n     *   <div class=\"pbox\" id=\"pager-box\">\n     *     <!-- pager box -->\n     *   </div>\n     * </div>\n     * \n     * <!-- list jst template -->\n     * <textarea name=\"jst\" id=\"jst-list\">\n     *   {list beg..end as y}\n     *     {var x=xlist[y]}\n     *     <div class=\"item\">\n               <a data-id=\"${x.id}\" data-action=\"delete\">删除</a>\n     *       <p>姓名：${x.name}</p>\n     *       <p>联系方式：${x.mobile}</p>\n     *     </div>\n     *   {/list}\n     * </textarea>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/klass',\n     *     'base/util',\n     *     'util/ajax/xdr',\n     *     'util/cache/abstract'\n     * ],function(_k,_u,_j,_t,_p){\n     *     var _pro;\n     *     // 自定义列表缓存\n     *     _p._$$CustomListCache = _k._$klass();\n     *     _pro = _p._$$CustomListCache._$extend(_t._$$CacheListAbstract);\n     * \n     *     // 实现数据载入逻辑\n     *     _pro.__doLoadList = function(_options){\n     *         var _onload = _options.onload;\n     *         // 补全请求数据，也可在模块层通过cache参数传入\n     *         var _data = _options.data||{};\n     *         _u._$merge(_data,{uid:'ww',sort:'xx',order:1});\n     *         switch(_options.key){\n     *                case 'user-list':\n     *                    // TODO load list from server\n     *                    _j._$request('/api/user/list',{\n     *                        type:'json',\n     *                        data:_u._$object2query(_data),\n     *                        onload:function(_json){\n     *                            // _json.code\n     *                            // _json.result\n     *                            _onload(_json.code==1?_json.result:null);\n     *                        },\n     *                        onerror:_onload._$bind(null);\n     *                    });\n     *                break;\n     *                // TODO other list load\n     *         }\n     *     };\n     * });\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     '/path/to/cache.js',\n     *     'util/list/pager'\n     * ],function(_t,_p){\n     *     // 构建列表模块，使用JST模版\n     *     _p._$$ListModulePG._$allocate({\n     *         limit:5,\n     *         parent:'list-box',\n     *         item:'jst-list', // 这里也可以传自己实现的item类型\n     *         cache:{\n     *             key:'user-list',// 此key必须是唯一的，对应了item中的值,也是删除选项的data-id\n     *             data:{uid:'ww',sort:'xx',order:1}, // <--- 列表加载时携带数据信息，此数据也可在cache层补全\n     *             klass:_t._$$CustomListCache\n     *         },\n     *         pager:{parent:'pager-box'}\n     *     });\n     * });\n     * ```\n     * \n     * @class   module:util/list/page._$$ListModulePG\n     * @extends module:util/list/module._$$ListModule\n     * \n     * @param   {Object} config - 可选配置参数\n     */\n    _p._$$ListModulePG = _k._$klass();\n    _pro = _p._$$ListModulePG._$extend(_t._$$ListModule);\n    /**\n     * 取当前偏移量的分页信息\n     *\n     * @protected\n     * @method module:util/list/page._$$ListModulePG#__getPageInfo\n     * @param  {Number} arg0 - 偏移位置\n     * @param  {Number} arg1 - 长度\n     * @return {Object}        分页信息，如：{index:1,total:4}\n     */\n    _pro.__getPageInfo = function(_offset,_length){\n        return this.__super(\n            this.__first,_offset,\n            this.__limit,_length\n        );\n    };\n    /**\n     * 根据页码计算偏移量\n     *\n     * @protected\n     * @method module:util/list/page._$$ListModulePG#__getOffsetByIndex\n     * @param  {Number} arg0 - 页码\n     * @return {Number}        偏移量\n     */\n    _pro.__getOffsetByIndex = function(_index){\n        var _offset = 0;\n        if (_index>1)\n            _offset = this.__first+(\n                _index-2)*this.__limit;\n        return _offset;\n    };\n    /**\n     * 页码变化处理逻辑\n     * \n     * @protected\n     * @method module:util/list/page._$$ListModulePG#__doChangePage\n     * @param  {Object} arg0 - 页码信息\n     * @return {Void}\n     */\n    _pro.__doChangePage = function(_event){\n        this.__super(_event);\n        if (!_event.stopped){\n            this.__doChangeOffset(\n                this.__getOffsetByIndex(_event.index)\n            );\n        }\n    };\n    /**\n     * 加载数据之前处理逻辑，显示数据加载中信息\n     * \n     * @protected\n     * @method module:util/list/page._$$ListModulePG#__doBeforeListLoad\n     * @return {Void}\n     */\n    _pro.__doBeforeListLoad = function(){\n        this.__doClearListBox();\n        this.__doShowMessage('onbeforelistload','列表加载中...');\n    };\n    /**\n     * 数据载入之后处理逻辑\n     * \n     * @protected\n     * @method module:util/list/page._$$ListModulePG#__doBeforeListShow\n     * @return {Void}\n     */\n    _pro.__doBeforeListShow = function(){\n        this.__super();\n        this.__doClearListBox();\n    };\n    /**\n     * 列表绘制之前处理逻辑\n     * \n     * @protected\n     * @method module:util/list/page._$$ListModulePG#__doBeforeListRender\n     * @return {Void}\n     */\n    _pro.__doBeforeListRender = function(_list,_offset,_limit){\n        var _info = this.__getPageInfo(_offset,_list.length);\n        if (this.__doSyncPager(_info.index,_info.total)) return !0;\n        this.__doSwitchPagerShow(_info.total>1?'':'none');\n    };\n    /**\n     * 列表为空时处理逻辑\n     * \n     * @protected\n     * @method module:util/list/page._$$ListModulePG#__doShowEmpty}\\\n     * @return {Void}\n     */\n    _pro.__doShowEmpty = function(){\n        this.__doShowMessage('onemptylist','没有列表数据！');\n    };\n    /**\n     * 通过事件回调检测显示信息\n     * \n     * @protected\n     * @method module:util/list/page._$$ListModulePG#__doShowMessage\n     * @param  {String} arg0 - 事件名称\n     * @param  {String} arg1 - 默认显示内容\n     * @param  {Object} arg2 - 扩展信息\n     * @return {Void} \n     */\n    _pro.__doRenderMessage = function(_message,_pos){\n        if (!_pos&&_u._$isString(_message)){\n            this.__lbox.innerHTML = _message;\n            return;\n        }\n        this.__super(_message,_pos);\n    };\n    /**\n     * 以jst模版方式绘制列表\n     * \n     * @protected\n     * @method module:util/list/page._$$ListModulePG#__doShowListByJST\n     * @return {Void}\n     */\n    _pro.__doShowListByJST = function(_html){\n        this.__lbox.innerHTML = _html;\n    };\n    /**\n     * 以item模版方式绘制列表\n     * \n     * @protected\n     * @method module:util/list/page._$$ListModulePG#__doShowListByItem\n     * @return {Void}\n     */\n    _pro.__doShowListByItem = function(_items){\n        this.__items = _items;\n    };\n    /**\n     * 添加列表项回调\n     * \n     * @protected\n     * @method module:util/list/page._$$ListModulePG#__cbItemAdd\n     * @return {Void}\n     */\n    _pro.__cbItemAdd = function(_event){\n        this.__doCheckResult(_event,'onafteradd');\n        if (!_event.stopped) this._$refresh();\n    };\n    /**\n     * 删除列表项回调\n     * \n     * @protected\n     * @method module:util/list/page._$$ListModulePG#__cbItemDelete\n     * @return {Void}\n     */\n    _pro.__cbItemDelete = function(_event){\n        this.__doCheckResult(_event,'onafterdelete');\n        if (!_event.stopped) this._$refresh();\n    };\n    /**\n     * 批量添加回调\n     *\n     * @protected\n     * @method module:util/list/page._$$ListModulePG#__cbAppendList\n     * @param  {Object} arg0 - 偏移量\n     * @param  {Object} arg1 - 数量\n     * @return {Void}\n     */\n    _pro.__cbAppendList = function(_offset,_limit){\n        var _index = 1;\n        if (!!this.__pager){\n            _index = this.__pager._$getIndex();\n        }\n        var _beg = this.__getOffsetByIndex(_index),\n            _end = _beg+(_index>1?this.__limit:this.__first);\n        if (_offset>=_end&&!!this.__pager){\n            var _info = this.__getPageInfo(\n                0,this._$getTotal()\n            );\n            this.__pager._$updateTotal(_info.total);\n            this.__doSwitchPagerShow(_info.total>1?'':'none');\n        }else{\n            this._$refresh();\n        }\n    };\n    /**\n     * 前向追加数据片段回调\n     *\n     * @protected\n     * @method module:util/list/page._$$ListModulePG#__cbUnshiftList\n     * @param  {Number} arg0 - 偏移量\n     * @param  {Number} arg1 - 数量\n     * @return {Void}\n     */\n    _pro.__cbUnshiftList = function(_offset,_limit){\n        var _index = 1;\n        if (!!this.__pager){\n            _index = this.__pager._$getIndex();\n        }\n        var _beg = this.__getOffsetByIndex(_index),\n            _info = this.__getPageInfo(\n                _beg,this._$getTotal()\n            );\n        this.__doChangePage({\n            last:_index,\n            index:_info.index\n        });\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/list/test/cache.list.custom.js",
    "content": "var f = function(){\n    var _  = NEJ.P,\n        _f = NEJ.F,\n        _u = _('nej.u'),\n        _e = _('nej.e'),\n        _p = _('nej.ut'),\n        _j = _('nej.j'),\n        _v = _('nej.v'),\n        _proCacheListCustom;\n    _p._$$CacheListCustom = NEJ.C();\n    _proCacheListCustom = _p._$$CacheListCustom._$extend(_p._$$CacheListAbstract);\n\n\t_proCacheListCustom.__doLoadList = function(_options){\n\t\tvar _key    = _options.key;\n\t\tvar _data   = _options.data;\n\t\tvar _offset = _options.offset;\n\t\tvar _limit  = _options.limit;\n\t\tvar _rkey   = _options.rkey;\n\t\tvar _onload = _options.onload;\n        // for test\n        var _arr = [];\n        var _len = _options.offset>=30?4:_options.limit;\n        for(var i=0;i<_len;i++){\n            _arr.push({id:+new Date+i,name:'user-'+(+new Date +i),loginTime:+new Date});\n        }\n        if (_options.offset==0){\n            this._$setTotal(_options.key,34);\n        }\n        window.setTimeout(_options.onload._$bind(_options,_arr),1000);\n//\t\t_j._$request('http://123.163.com:3000/xhr/getLog',{\n//                type:'json',\n//                method:'POST',\n//                data:{offset:_offset,limit:_limit},\n//                timeout:1000,\n//                onload:_onload._$bind(this),\n//                onerror:function(_error){\n//\t\t\t\t}\n//            }\n//        );\n\t};\n\n\t/**\n     * 从服务器中获取一项\n     * @param {Object} _options\n     */\n\t_proCacheListCustom.__doLoadItem = function(_options){\n        var _id     = _options.id;\n        var _key    = _options.key;\n        var _rkey   = _options.rkey;\n        var _onload = _options.onload;\n        _j._$request('http://123.163.com:3000/xhr/getLog',{\n                type:'json',\n                method:'POST',\n                data:{rkey:_rkey},\n                timeout:1000,\n                onload:_onload._$bind(this),\n                onerror:function(_error){}\n            }\n        );\n    };\n\n    /**\n     * 增加一项到服务器\n     * @param {Object} _options\n     */\n\t_proCacheListCustom.__doAddItem = function(_options){\n        var _key  = _options.key;\n        var _item = _options.item;\n\t\tvar _push = _options.push;\n        var _onload = _options.onload;\n        _j._$request('http://123.163.com:3000/xhr/getLog',{\n                type:'json',\n                method:'POST',\n                data:{},\n                timeout:1000,\n                onload:_onload._$bind(this),\n                onerror:function(_error){}\n            }\n        );\n    };\n\n\t/**\n     * 从服务器中删除一项\n     * @param {Object} _options\n     */\n\t_proCacheListCustom.__doDeleteItem = function(_options){\n        // var _id     = _options.id;\n        // var _key    = _options.key;\n        // var _rkey   = _options.rkey;\n        // var _onload = _options.onload;\n        // _j._$request('http://123.163.com:3000/xhr/getLog',{\n        //         type:'json',\n        //         method:'POST',\n        //         data:{rkey:_rkey},\n        //         timeout:1000,\n        //         onload:_onload._$bind(this),\n        //         onerror:function(_error){}\n        //     }\n        // );\n        // for test\n        window.setTimeout(function(){\n            var _event = _options.onload(!0);\n            // _v._$dispatchEvent(\n            //     _p._$$CacheListCustom,'listchange',_event);\n        },500);\n    };\n\n\t/**\n     * 更新服务器中的一项\n     * @param {Object} _options\n     */\n\t_proCacheListCustom.__doUpdateItem = function(_options){\n        var _id     = _options.id;\n        var _key    = _options.key;\n        var _rkey   = _options.rkey;\n        var _onload = _options.onload;\n        _j._$request('http://123.163.com:3000/xhr/getLog',{\n                type:'json',\n                method:'POST',\n                data:{rkey:_rkey},\n                timeout:1000,\n                onload:_onload._$bind(this),\n                onerror:function(_error){}\n            }\n        );\n    };\n\n}\ndefine('{pro}cache.list.custom.js',[\n\t'{lib}util/event/event.js',\n\t'{lib}util/cache/abstract.js'],f);\n\n"
  },
  {
    "path": "src/util/list/test/module.pager.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<title>module.pager.test</title>\n  \t\t<link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n\t<body>\n\t\t<h1 id=\"qunit-header\">Qunit dwr test</h1>\n\t\t<h2 id=\"qunit-banner\"></h2>\n\t\t<div id=\"qunit-testrunner-toolbar\"></div>\n\t\t<h2 id=\"qunit-userAgent\"></h2>\n\t\t<ol id=\"qunit-tests\"></ol>\n \t\t<div id=\"qunit-fixture\"></div>\n \t\t<div class=\"mbox\">\n          <div class=\"lbox\" id=\"list-box\">\n            <!-- list box -->\n          </div>\n          <div class=\"pbox\" id=\"pager-box\">\n            <!-- pager box -->\n          </div>\n        </div>\n        \n        <!-- list jst template -->\n        <textarea name=\"jst\" id=\"jst-list\" style=\"visibility:hidden;\">\n          {list beg..end as y}\n            {var x=xlist[y]}\n            <div class=\"itm\" id=\"${x.id|seed}\">\n              <a class=\"fr\" href=\"#\" data-id=\"${x.name}\">[删除]</a>\n              <p>${beg+y_index}. ${x.name}：${x.loginTime|format:'yyyy-MM-dd HH:mm:ss'}</p>\n            </div>\n          {/list}\n        </textarea>\n       <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./module.pager.test.js\"></script>\n\t</body>\n</html>"
  },
  {
    "path": "src/util/list/test/module.pager.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"module.pager\");\n    \n\tvar _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v'),\n        _p = _('nej.ut');\n\t\n\ttest('module.pager test',function(){\n\t\texpect(0);\n        _e._$parseTemplate('jst-list');\n\t\tvar _lmgp = _p._$$ListModulePG._$allocate({\n     \t\titem:'jst-list',\n            parent:'list-box',\n            pager:{parent:'pager-box'},\n     \t\tcache:{\n     \t\t\tkey:'name',\n                klass:_p._$$CacheListCustom\n     \t\t}\n\t\t});\n\t});\n    //开始单元测试\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}module.pager.test.js',\n    ['{lib}util/list/module.pager.js','{pro}cache.list.custom.js'],f);\n});\n  "
  },
  {
    "path": "src/util/list/waterfall.js",
    "content": "/*\n * ------------------------------------------\n * 瀑布式列表模块实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/list/waterfall */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/event',\n    'base/element',\n    'base/util',\n    'util/template/tpl',\n    './module.js'\n],function(NEJ,_k,_v,_e,_u,_l,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 瀑布式列表模块\n     * \n     * 结构举例\n     * ```html\n     * <div class=\"mbox\">\n     *   <div class=\"lbox\" id=\"list-box\">\n     *     <!-- list box -->\n     *   </div>\n     *   <div class=\"mbtn\" id=\"more-btn\"> load more button </div>\n     * </div>\n     * \n     * <!-- list jst template -->\n     * <textarea name=\"jst\" id=\"jst-list\">\n     *   {list beg..end as y}\n     *     {var x=xlist[y]}\n     *     <div class=\"item\">\n               <a data-id=\"${x.id|x.name}\" data-action=\"delete\">删除</a>\n     *       <p>姓名：${x.name}</p>\n     *       <p>联系方式：${x.mobile}</p>\n     *     </div>\n     *   {/list}\n     * </textarea>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/klass',\n     *     'base/util',\n     *     'util/ajax/xdr',\n     *     'util/cache/abstract'\n     * ],function(_k,_u,_j,_t,_p){\n     *     var _pro;\n     *     // 自定义列表缓存\n     *     _p._$$CustomListCache = _k._$klass();\n     *     _pro = _p._$$CustomListCache._$extend(_t._$$CacheListAbstract);\n     * \n     *     // 实现数据载入逻辑\n     *     _pro.__doLoadList = function(_options){\n     *         var _onload = _options.onload;\n     *         // 补全请求数据，也可在模块层通过cache参数传入\n     *         var _data = _options.data||{};\n     *         _u._$merge(_data,{uid:'ww',sort:'xx',order:1});\n     *         switch(_options.key){\n     *                case 'user-list':\n     *                    // TODO load list from server\n     *                    _j._$request('/api/user/list',{\n     *                        type:'json',\n     *                        data:_u._$object2query(_data),\n     *                        onload:function(_json){\n     *                            // _json.code\n     *                            // _json.result\n     *                            _onload(_json.code==1?_json.result:null);\n     *                        },\n     *                        onerror:_onload._$bind(null);\n     *                    });\n     *                break;\n     *                // TODO other list load\n     *         }\n     *     };\n     * });\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     '/path/to/cache.js',\n     *     'util/list/waterfall'\n     * ],function(_t,_p){\n     *     // 构建列表模块，使用JST模版\n     *     _p._$$ListModuleWF._$allocate({\n     *         limit:5,\n     *         parent:'list-box',\n     *         item:'jst-list', // 这里也可以传自己实现的item类型\n     *         cache:{\n     *             key:'user-list',// 此key必须是唯一的，对应了item中的值,也是删除选项的data-id\n     *             data:{uid:'ww',sort:'xx',order:1}, // <--- 列表加载时携带数据信息，此数据也可在cache层补全\n     *             klass:_t._$$CustomListCache\n     *         },\n     *         pager:{parent:'pager-box'}\n     *     });\n     * });\n     * ```\n     * \n     * @class   module:util/list/waterfall._$$ListModuleWF\n     * @extends module:util/list/module._$$ListModule\n     * \n     * @param    {Object}      config - 可选配置参数\n     * @property {String|Node} more   - 添加更多列表项按钮节点\n     * @property {String|Node} sbody  - 滚动条所在容器，支持onscroll事件\n     * @property {Number}      delta  - 触发自动加载更多时距离滚动容器底部的偏移量，单位px，默认30\n     * @property {Number}      count  - 指定加载多少次后出现分页器\n     * @property {Number}      number - 初始加载次数，小于等于count数有效\n     */\n    _p._$$ListModuleWF = _k._$klass();\n    _pro = _p._$$ListModuleWF._$extend(_t._$$ListModule);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__doResetMoreBtn(_options.more);\n        this.__sbody = _e._$get(_options.sbody);\n        this.__doInitDomEvent([[\n            this.__sbody,'scroll',\n            this.__onCheckScroll._$bind(this)\n        ]]);\n        var _delta = _options.delta;\n        if (_delta==null) _delta = 30;\n        this.__delta = Math.max(0,_delta);\n        var _count = parseInt(_options.count)||0;\n        this.__count = Math.max(0,_count);\n        var _number = parseInt(_options.number)||0;\n        if (_number>1&&_number<=_count){\n            this.__number = _number;\n        }\n        this.__super(_options);\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        if (this.__stimer){\n            window.clearTimeout(this.__stimer);\n            delete this.__stimer;\n        }\n        delete this.__nmore;\n        delete this.__sbody;\n        delete this.__endskr;\n        delete this.__nexting;\n    };\n    /**\n     * 取当前偏移量的分页信息\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__getPageInfo\n     * @param  {Number} arg0 - 偏移位置\n     * @param  {Number} arg1 - 长度\n     * @return {Object}        分页信息，如：{index:1,total:4}\n     */\n    _pro.__getPageInfo = function(_offset,_length){\n        var _point = this.__first+(this.__count-1)*this.__limit,\n            _limit = this.__count*this.__limit;\n        return this.__super(_point,_offset,_limit,_length);\n    };\n    /**\n     * 重置载入更多按钮\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__doResetMoreBtn\n     * @param  {String|Node} arg0 - 按钮节点\n     * @return {Void}\n     */\n    _pro.__doResetMoreBtn = function(_more){\n        this.__nmore = _e._$get(_more);\n        this.__doInitDomEvent([[\n            this.__nmore,'click',\n            this._$next._$bind(this)\n        ]]);\n    };\n    /**\n     * 延时加载下一页数据\n     *\n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__doLoadNextByTimer\n     * @return {Void}\n     */\n    _pro.__doLoadNextByTimer = function(){\n        if (!this.__endskr){\n            this._$next();\n        }\n    };\n    /**\n     * 检查滚动条\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__doCheckScroll\n     * @return {Void}\n     */\n    _pro.__doCheckScroll = function(_element){\n        if (this.__endskr||!_element||\n           !this.__lbox.clientHeight) return;\n        if (!_element.scrollHeight)\n            _element = _e._$getPageBox();\n        var _offset = _e._$offset(this.__lbox,this.__sbody),\n            _delta = _offset.y+this.__lbox.offsetHeight-\n                     _element.scrollTop-_element.clientHeight,\n            _noscroll = _element.scrollHeight<=_element.clientHeight;\n        if (_delta<=this.__delta||(_noscroll&&!this.__endskr)){\n            // render first\n            if (this.__stimer){\n                window.clearTimeout(this.__stimer);\n            }\n            this.__stimer = window.setTimeout(\n                this.__doLoadNextByTimer._$bind(this),0\n            );\n        }\n    };\n    /**\n     * 检查滚动情况\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__onCheckScroll\n     * @return {Void}\n     */\n    _pro.__onCheckScroll = function(_event){\n        if (this.__endskr) return;\n        var _node = _v._$getElement(_event);\n        if (!_node){\n            _node = _e._$getPageBox();\n        }\n        this.__doCheckScroll(_node);\n    };\n    /**\n     * 页码变化处理逻辑\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__doChangePage\n     * @param  {Object} 页码信息\n     * @return {Void}\n     */\n    _pro.__doChangePage = function(_event){\n        this.__super(_event);\n        if (!_event.stopped){\n            this.__doClearListBox();\n            var _offset = 0;\n            if (_event.index>1){\n                _offset = this.__first+((\n                    _event.index-1)*this.__count-1)*this.__limit;\n            }\n            this.__offset = _offset;\n            this._$next();\n        }\n    };\n    /**\n     * 生成请求对象信息\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__doGenRequestOpt\n     * @param  {Object} arg0 - 预处理请求信息\n     * @return {Object}        处理后请求信息\n     */\n    _pro.__doGenRequestOpt = function(_options){\n        if (!!this.__number){\n            var _delta = _options.offset>0?this.__limit:this.__first,\n                _limit = _delta+this.__limit*(this.__number-1);\n            this.__offset = _options.offset+_limit;\n            _options.data.limit = _limit;\n            _options.limit = _limit;\n            delete this.__number;\n        }\n        return _options;\n    };\n    /**\n     * 数据列表载入完成回调\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__cbListLoad\n     * @param  {Object} arg0 - 请求信息\n     * @return {Void}\n     */\n    _pro.__cbListLoad = function(_options){\n        delete this.__nexting;\n        if (!this.__super(_options)){\n            this._$resize();\n        }\n    };\n    /**\n     * 列表变化回调（删除/添加）\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__cbListChange\n     * @return {Void}\n     */\n    _pro.__cbListChange = function(_event){\n        if (!!_event.key&&\n            _event.key!=this.__ropt.key){\n            return;\n        }\n        switch(_event.action){\n            case 'refresh':\n            case 'append':\n                delete this.__nexting;\n            break;\n        }\n        this.__super(_event);\n    };\n    /**\n     * 加载数据之前处理逻辑，显示数据加载中信息\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__doBeforeListLoad\n     * @return {Void}\n     */\n    _pro.__doBeforeListLoad = function(){\n        this.__doShowMessage('onbeforelistload','列表加载中...');\n        _e._$setStyle(this.__nmore,'display','none');\n    };\n    /**\n     * 列表绘制之前处理逻辑\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__doBeforeListRender\n     * @return {Void}\n     */\n    _pro.__doBeforeListRender = function(_list,_offset,_limit){\n        var _length = _list.length,\n            _ended = _list.loaded\n                   ? _offset+_limit>=_length\n                   : _offset+_limit>_length;\n        this.__offset = Math.min(this.__offset,_length);\n        _e._$setStyle(this.__nmore,'display',_ended?'none':'');\n        if (_ended) this.__endskr = !0;\n        if (this.__count>0){\n            // check pager\n            var _info = this.__getPageInfo(_offset,_list.length);\n            if (this.__doSyncPager(_info.index,_info.total)) return !0;\n            // check scroll end\n            var _delta = this.__first-this.__limit,\n                _number = this.__count*this.__limit;\n            this.__endskr = (_offset+_limit-_delta)%_number==0||_ended;\n            // sync more button and pager\n            _e._$setStyle(\n                this.__nmore,'display',\n                this.__endskr?'none':''\n            );\n            this.__doSwitchPagerShow(\n                this.__endskr&&_info.total>1?'':'none'\n            );\n        }\n    };\n    /**\n     * 列表为空时处理逻辑\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__doShowEmpty\n     * @return {Void}\n     */\n    _pro.__doShowEmpty = function(){\n        this.__offset = 0;\n        this.__endskr = !0;\n        this.__doShowMessage('onemptylist','没有列表数据！');\n    };\n    /**\n     * 以jst模版方式绘制列表\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__doShowListByJST\n     * @return {Void}\n     */\n    _pro.__doShowListByJST = function(_html,_pos){\n        this.__lbox.insertAdjacentHTML(_pos||'beforeEnd',_html);\n    };\n    /**\n     * 以item模版方式绘制列表\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__doShowListByItem\n     * @return {Void}\n     */\n    _pro.__doShowListByItem = function(_items){\n        this.__items = this.__items||[];\n        if (_u._$isArray(_items)){\n            _r.push.apply(this.__items,_items);\n        }else{\n            this.__items.push(_items);\n        }\n    };\n    /**\n     * 添加列表项回调\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__cbItemAdd\n     * @return {Void}\n     */\n    _pro.__cbItemAdd = function(_event){\n        _e._$removeByEC(this.__ntip);\n        this.__doCheckResult(_event,'onafteradd');\n        var _flag = _event.flag;\n        if (_event.stopped||!_flag) return;\n        // with pager\n        if (this.__count>0){\n            this.__doRefreshByPager();\n            return;\n        }\n        // without pager\n        this.__offset += 1;\n        _flag==-1 ? this._$unshift(_event.data)\n                  : this._$append(_event.data);\n    };\n    /**\n     * 删除列表项回调\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__cbItemDelete\n     * @return {Void}\n     */\n    _pro.__cbItemDelete = function(_event){\n        this.__doCheckResult(_event,'onafterdelete');\n        if (_event.stopped) return;\n        // with pager\n        if (this.__count>0){\n            this.__doRefreshByPager();\n            return;\n        }\n        // without pager\n        var _id = _event.data[this.__iopt.pkey];\n        if (!!this.__items){\n            var _item = _l._$getItemById(\n                    this.__getItemId(_id)\n                ),\n                _index = _u._$indexOf(this.__items,_item);\n            if (_index>=0){\n                this.__items.splice(_index,1);\n                this.__offset -= 1;\n            }\n            if (!!_item) _item._$recycle();\n        }else{\n            var _node = this._$getItemBody(_id);\n            if (!!_node) this.__offset -= 1;\n            _e._$remove(_node);\n        }\n        if (this.__offset<=0) this._$next();\n    };\n    /**\n     * 批量添加回调\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__cbAppendList\n     * @param  {Object} arg0 - 偏移量\n     * @param  {Object} arg1 - 数量\n     * @return {Void}\n     */\n    _pro.__cbAppendList = function(_offset,_limit){\n        if (_offset!=this.__offset) return;\n        // check list loaded\n        if (this._$isLoaded()){\n            this.__endskr = !1;\n            this._$resize();\n        }\n    };\n    /**\n     * 前向追加数据片段回调\n     * \n     * @protected\n     * @method module:util/list/waterfall._$$ListModuleWF#__cbUnshiftList\n     * @param  {Number} arg0 - 偏移量\n     * @param  {Number} arg1 - 数量\n     * @return {Void}\n     */\n    _pro.__cbUnshiftList = function(_offset,_limit){\n        if (_offset!=0) return;\n        var _xlist = this.__cache._$getListInCache(\n            this.__ropt.key\n        );\n        for(var i=_limit-1;i>=0;i--){\n            this._$unshift(_xlist[i]);\n        }\n    };\n    /**\n     * 重置大小触发滚动条修正\n     * \n     * @method module:util/list/waterfall._$$ListModuleWF#_$resize\n     * @return {Void}\n     */\n    _pro._$resize = function(){\n        // if not scroll check next\n        var _element = this.__sbody;\n        if (!_element||this.__endskr) return;\n        this.__doCheckScroll(this.__sbody);\n    };\n    /**\n     * 刷新模块\n     * \n     * @method module:util/list/waterfall._$$ListModuleWF#_$refresh\n     * @param  {Number} 刷新到的页码\n     * @return {Void}\n     */\n    _pro._$refresh = function(){\n        delete this.__endskr;\n        this.__super();\n    };\n    /**\n     * 载入更多列表\n     * \n     * @method module:util/list/waterfall._$$ListModuleWF#_$next\n     * @return {Void}\n     */\n    _pro._$next = function(){\n        // lock loading\n        if (!!this.__nexting) \n            return;\n        this.__nexting = !0;\n        // update offset first for\n        // offset adjust after list loaded\n        var _offset = this.__offset;\n        this.__offset += _offset==0?\n            this.__first:this.__limit;\n        this.__doChangeOffset(_offset);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/media/audio.js",
    "content": "/*\n * ------------------------------------------\n * 音频播放控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/media/audio */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    './media.js'\n],function(NEJ,_k,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 音频播放控件\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/media/audio'\n     * ],function(_t){\n     *     // 首先生成播放对象,只负责逻辑部分，要配合UI来使用\n     *     // preload：是否预加载\n     *     // url：音频地址\n     *     var _audio = _t._$$MediaAudio._$allocate({\n     *         preload:false,\n     *         url:'http://127.0.0.1:8000/nej-baseline/res/test.mp3',\n     *         onstatechange:function(_event){\n     *             // 状态改变的回调\n     *             // 0 | 当前停止状态\n     *             // 1 | 当前缓冲状态\n     *             // 2 | 当前播放状态\n     *             // 3 | 当前暂停状态\n     *             // 4 | 播放结束状态\n     *         }\n     *     });\n     *     \n     *     // 开始播放\n     *     _audio._$play();\n     *     // 暂停播放\n     *     _audio._$pause();\n     *     // 停止播放\n     *     _audio._$stop();\n     * });\n     * ```\n     * \n     * @class    module:util/media/audio._$$MediaAudio\n     * @extends  module:util/media/media._$$Media\n     * @param    {Object} config - 可选配置参数\n     * @property {String} url    - 音频地址\n     */\n    _p._$$MediaAudio = _k._$klass();\n    _pro = _p._$$MediaAudio._$extend(_t._$$Media);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/media/audio._$$MediaAudio#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__audio = new Audio();\n        this.__doInitDomEvent([[\n            this.__audio,'loadstart',\n            this.__onLoading._$bind(this)\n        ],[\n            this.__audio,'timeupdate',\n            this.__onPlaying._$bind(this)\n        ],[\n            this.__audio,'pause',\n            this.__onPause._$bind(this)\n        ],[\n            this.__audio,'volumechange',\n            this.__onVolumeChange._$bind(this)\n        ],[\n            this.__audio,'ended',\n            this.__onStop._$bind(this)\n        ],[\n            this.__audio,'error',\n            this.__onError._$bind(this)\n        ]]);\n        this.__super(_options);\n    };\n    /**\n     * 销毁控件\n     * \n     * @protected\n     * @method module:util/media/audio._$$MediaAudio#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__audio;\n    };\n    /**\n     * 执行播放操作\n     * \n     * @protected\n     * @method module:util/media/audio._$$MediaAudio#__doPlay\n     * @return {Void}\n     */\n    _pro.__doPlay = function(){\n        if (this.__audio.src!=this.__source){\n            this.__audio.src = this.__source;\n            this.__source = this.__audio.src;\n        }\n        this.__audio.play();\n    };\n    /**\n     * 执行暂停操作\n     * \n     * @protected\n     * @method module:util/media/audio._$$MediaAudio#__doPause\n     * @return {Void}\n     */\n    _pro.__doPause = function(){\n        this.__audio.pause();\n    };\n    /**\n     * 执行停止操作\n     * \n     * @protected\n     * @method module:util/media/audio._$$MediaAudio#__doStop\n     * @return {Void}\n     */\n    _pro.__doStop = function(){\n        this.__stopped = !0;\n        this.__doPause();\n        if (this.__state==3){\n            this.__onPause();\n        }\n    };\n    /**\n     * 文件载入触发事件\n     * \n     * @protected\n     * @method module:util/media/audio._$$MediaAudio#__onLoading\n     * @return {Void}\n     */\n    _pro.__onLoading = function(){\n        if (!this.__audio.paused){\n            this.__doStateChange(1);\n        }\n    };\n    /**\n     * 暂停触发事件\n     * \n     * @protected\n     * @method module:util/media/audio._$$MediaAudio#__onPause\n     * @return {Void}\n     */\n    _pro.__onPause = function(){\n        var _state = !this.__stopped?3:0;\n        this.__stopped = !1;\n        this.__doStateChange(_state);\n        if (_state==0){\n            try{\n                this.__audio.removeAttribute('src');\n            }catch(ex){\n                // ignore\n            }\n        }\n    };\n    /**\n     * 播放过程触发事件\n     * \n     * @protected\n     * @method module:util/media/audio._$$MediaAudio#__onPlaying\n     * @return {Void}\n     */\n    _pro.__onPlaying = function(){\n        var _duration = this.__audio.duration;\n        // for stop or loading\n        if (this.__audio.paused||isNaN(_duration)){\n            return;\n        }\n        // for playing\n        this.__doStateChange(2);\n        this._$dispatchEvent(\n            'ontimeupdate',{\n                duration:this.__audio.duration,\n                current:this.__audio.currentTime\n            }\n        );\n    };\n    /**\n     * 播放错误事件\n     *\n     * @protected\n     * @method module:util/media/audio._$$MediaAudio#__onError\n     * @param  {Event} 事件信息\n     * @return {Void}\n     */\n    _pro.__onError = function(_event){\n        this.__doError();\n        var _error = this.__audio.error;\n        this._$dispatchEvent('onerror',{\n            code:_error.code\n        });\n    };\n    /**\n     * 设置播放时间\n     * \n     * @protected\n     * @method module:util/media/audio._$$MediaAudio#__setCurrentTime\n     * @return {Void}\n     */\n    _pro.__setCurrentTime = function(_time){\n        if (this.__state==1) return;\n        this.__audio.currentTime = _time||0;\n    };\n    /**\n     * 获取播放时间\n     * \n     * @protected\n     * @method module:util/media/audio._$$MediaAudio#__getCurrentTime\n     * @return {Number} 当前时间\n     */\n    _pro.__getCurrentTime = function(){\n        return this.__audio.currentTime;\n    };\n    /**\n     * 设置音量\n     * \n     * @protected\n     * @method module:util/media/audio._$$MediaAudio#__setVolume\n     * @return {Void}\n     */\n    _pro.__setVolume = function(_volume){\n        this.__audio.volume = _volume;\n    };\n    /**\n     * 获取音量\n     * \n     * @protected\n     * @method module:util/media/audio._$$MediaAudio#__getVolume\n     * @return {Number} 音量值\n     */\n    _pro.__getVolume = function(){\n        return this.__audio.volume;\n    };\n    /**\n     * 取媒体总时长\n     * \n     * @method module:util/media/audio._$$MediaAudio#_$duration\n     * @return {Number} 媒体总时长\n     */\n    _pro._$duration = function(){\n        return !this.__audio?0:this.__audio.duration;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/media/flash.js",
    "content": "/*\n * ------------------------------------------\n * 音频播放控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/media/flash */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/config',\n    'util/flash/flash',\n    './media.js'\n],function(NEJ,_k,_c,_e,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 音频播放控件\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/media/flash'\n     * ],function(_t){\n     *     // 首先生成播放对象,只负责逻辑部分，要配合UI来使用\n     *     // preload：是否预加载\n     *     // url：音频地址\n     *     var _media = _t._$$MediaFlash._$allocate({\n     *         preload:false,\n     *         url:'http://127.0.0.1:8000/nej-baseline/res/test.mp3',\n     *         onstatechange:function(_event){\n     *             // 状态改变的回调\n     *             // 0 | 当前停止状态\n     *             // 1 | 当前缓冲状态\n     *             // 2 | 当前播放状态\n     *             // 3 | 当前暂停状态\n     *             // 4 | 播放结束状态\n     *         }\n     *     });\n     *     \n     *     // 开始播放\n     *     _media._$play();\n     *     // 暂停播放\n     *     _media._$pause();\n     *     // 停止播放\n     *     _media._$stop();\n     * });\n     * ```\n     * \n     * @class    module:util/media/flash._$$MediaFlash\n     * @extends  module:util/media/media._$$Media\n     * \n     * @param    {Object} config - 可选配置参数\n     * @property {String} url    - 音频地址\n     */\n    _p._$$MediaFlash = _k._$klass();\n    _pro = _p._$$MediaFlash._$extend(_t._$$Media);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:util/media/flash._$$MediaFlash#__init\n     * @return {Void}\n     */\n    _pro.__init = (function(){\n        var _onReady = function(_flash){\n            this.__audio = _flash;\n            if (!!this.__action){\n                this.__action.call(this);\n                delete this.__action;\n            }\n        };\n        return function(){\n            this.__super();\n            _e._$flash({\n                hidden:!0,\n                src:_c._$get('audio.swf'),\n                onready:_onReady._$bind(this),\n                onended:this.__onStop._$bind(this),\n                onpause:this.__onPause._$bind(this),\n                onseeking:this.__onLoading._$bind(this),\n                onprogress:this.__onLoading._$bind(this),\n                ontimeupdate:this.__onPlaying._$bind(this),\n                onvolumechange:this.__onVolumeChange._$bind(this),\n                onerror:this.__onError._$bind(this)\n            });\n        };\n    })();\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/media/flash._$$MediaFlash#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__action;\n    };\n    /**\n     * 执行播放操作\n     *\n     * \n     * @protected\n     * @method module:util/media/flash._$$MediaFlash#__doPlay\n     * @return {Void}\n     */\n    _pro.__doPlay = function(){\n        if (!!this.__audio){\n            if (!!this.__source){\n                this.__audio.nej_setSrc(this.__source);\n                delete this.__source;\n            }\n            this.__audio.nej_play();\n        }else{\n            this.__action = this.__doPlay;\n        }\n    };\n    /**\n     * 执行暂停操作\n     * \n     * @protected\n     * @method module:util/media/flash._$$MediaFlash#__doPause\n     * @return {Void}\n     */\n    _pro.__doPause = function(){\n        if (!!this.__audio){\n            this.__audio.nej_pause();\n        }else{\n            this.__action = this.__doPause;\n        }\n    };\n    /**\n     * 执行停止操作\n     * \n     * @protected\n     * @method module:util/media/flash._$$MediaFlash#__doStop\n     * @return {Void}\n     */\n    _pro.__doStop = function(){\n        if (!!this.__audio){\n            this.__audio.nej_stop();\n            this.__doStateChange(0);\n        }else{\n            this.__action = this.__doStop;\n        }\n    };\n    /**\n     * 文件载入触发事件\n     * \n     * @protected\n     * @method module:util/media/flash._$$MediaFlash#__onLoading\n     * @return {Void}\n     */\n    _pro.__onLoading = function(){\n        this.__doStateChange(1);\n    };\n    /**\n     * 暂停触发事件\n     * \n     * @protected\n     * @method module:util/media/flash._$$MediaFlash#__onPause\n     * @return {Void}\n     */\n    _pro.__onPause = function(){\n        this.__doStateChange(3);\n    };\n    /**\n     * 播放过程触发事件\n     * \n     * @protected\n     * @method module:util/media/flash._$$MediaFlash#__onPlaying\n     * @return {Void}\n     */\n    _pro.__onPlaying = function(_event){\n        this.__doStateChange(2);\n        this._$dispatchEvent(\n            'ontimeupdate',{\n                duration:_event.duration,\n                current:_event.currentTime\n            }\n        );\n        // check volume\n        if (this.__dtvol!=null){\n            var _volume = this.__dtvol;\n            delete this.__dtvol;\n            this.__setVolume(_volume);\n        }\n    };\n    /**\n     * 播放错误事件\n     *\n     * @protected\n     * @method module:util/media/flash._$$MediaFlash#__onError\n     * @param  {Event} 事件信息\n     * @return {Void}\n     */\n    _pro.__onError = function(_event){\n        this.__doError();\n        this._$dispatchEvent('onerror',{\n            code:_event.code\n        });\n    };\n    /**\n     * 设置播放时间\n     * \n     * @protected\n     * @method module:util/media/flash._$$MediaFlash#__setCurrentTime\n     * @return {Void}\n     */\n    _pro.__setCurrentTime = function(_time){\n        if (this.__state==1) return;\n        this.__audio.nej_seek(_time||0);\n    };\n    /**\n     * 获取播放时间\n     * \n     * @protected\n     * @method module:util/media/flash._$$MediaFlash#__getCurrentTime\n     * @return {Number} 当前时间\n     */\n    _pro.__getCurrentTime = function(){\n        return this.__audio.nej_flash_get_currentTime();\n    };\n    /**\n     * 设置音量\n     * \n     * @protected\n     * @method module:util/media/flash._$$MediaFlash#__setVolume\n     * @return {Void}\n     */\n    _pro.__setVolume = function(_volume){\n        if (!this.__audio){\n            this.__dtvol = _volume;\n            return;\n        }\n        try{\n            this.__audio.nej_flash_set_volume(_volume);\n        }catch(e){\n            this.__dtvol = _volume;\n        }\n    };\n    /**\n     * 获取音量\n     * \n     * @protected\n     * @method module:util/media/flash._$$MediaFlash#__getVolume\n     * @return {Number} 音量值\n     */\n    _pro.__getVolume = function(){\n        if (!this.__audio) return;\n        return this.__audio.nej_flash_get_volume();\n    };\n    /**\n     * 取媒体总时长\n     * \n     * @method module:util/media/flash._$$MediaFlash#_$duration\n     * @return {Number} 媒体总时长\n     */\n    _pro._$duration = function(){\n        return !this.__audio?0:this.__audio.nej_flash_get_duration();\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/media/media.js",
    "content": "/*\n * ------------------------------------------\n * 多媒体控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/media/media */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'util/event'\n],function(NEJ,_k,_t,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 多媒体控件基类\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/media/media'\n     * ],function(_t,_p,_o,_f,_r){\n     *     // 第一步：继承此基类\n     *     _pro = _p._$$MediaAudio._$extend(_t._$$Media);\n     *\n     *     _pro.__reset = function(){\n     *         this.__audio = new Audio();\n     *         // TODO\n     *         this.__super();\n     *     };\n     *     // 子类实现以下方法\n     *\n     *     // 获取播放对象\n     *     _pro.__getMedia = function(){\n     *         return this.__audio;\n     *     };\n     *     //  预加载操作\n     *     _pro.__doPreload = function(){\n     *          if (this.__audio.src!=this.__source){\n     *              this.__audio.src = this.__source;\n     *              this.__source = this.__audio.currentSrc;\n     *          }\n     *     };\n     *     //  执行播放操作\n     *     _pro.__doPlay = function(){\n     *         this.__audio.play();\n     *     };\n     *     //  执行暂停操作\n     *     _pro.__doPause = function(){\n     *         this.__audio.pause();\n     *     };\n     * });\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *  NEJ.define([\n     *      'path/to/custom/media.js'\n     *  ],function(_t,_p,_o,_f,_r){\n     *      // 第二步：生成子类的实例\n     *      var _mda = _t._$$MediaAudio._$allocate({\n     *          preload:false,\n     *          url:'http://127.0.0.1:8000/nej-baseline/res/test.mp3',\n     *          onstatechange:function(_event){\n     *              // 状态改变的回调\n     *              // 0 | 当前停止状态\n     *              // 1 | 当前缓冲状态\n     *              // 2 | 当前播放状态\n     *              // 3 | 当前暂停状态\n     *              // 4 | 播放结束状态\n     *          }\n     *      });\n     *      \n     *      // 开始播放\n     *      _mda._$play();\n     *      // 暂停播放\n     *      _mda._$pause();\n     *      // 停止播放\n     *      _mda._$stop();\n     *   });\n     * ```\n     *\n     * @class    module:util/media/media._$$Media\n     * @extends  module:util/event._$$EventTarget\n     *\n     * @param    {Object} config - 可选配置参数\n     * @property {String} url    - 多媒体文件地址\n     * @property {Number} volume - 音量大小，0-100之间的数值\n     */\n    /**\n     * 状态变化触发事件，播放状态说明\n     * \n     * | 状态 | 说明 |\n     * | :--- | :--- |\n     * | 0 | 当前停止状态 |\n     * | 1 | 当前缓冲状态 |\n     * | 2 | 当前播放状态 |\n     * | 3 | 当前暂停状态 |\n     * | 4 | 播放结束状态 |\n     *\n     * @event    module:util/media/media._$$Media#onstatechange\n     * @param    {Object} event  - 可选配置参数\n     * @property {Number} state  - 播放状态\n     * @property {Object} target - 播放信息\n     */\n    /**\n     * 播放过程触发事件\n     * \n     * @event    module:util/media/media._$$Media#ontimeupdate\n     * @param    {Object} event    - 可选配置参数\n     * @property {Float}  current  - 当前时间，单位秒\n     * @property {Float}  duration - 总时长，单位秒\n     */\n    /**\n     * 音量变化触发事件\n     * \n     * @event    module:util/media/media._$$Media#onvolumechange\n     * @param    {Object} event  - 可选配置参数\n     * @property {Float}  volume - 当前音量，0-100之间的数值\n     */\n    /**\n     * 播放错误触发事件\n     * \n     * @event module:util/media/media._$$Media#onerror\n     * @param {Object} event - 错误信息\n     */\n    _p._$$Media = _k._$klass();\n    _pro = _p._$$Media._$extend(_t._$$EventTarget);\n    /**\n     * 重置控件\n     * \n     * @protected\n     * @method module:util/media/media._$$Media#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__state = 0;\n        this._$source(_options.url);\n        if (_options.volume!=null){\n            this._$volume(_options.volume);\n        }\n        this.__super(_options);\n    };\n    /**\n     * 销毁控件\n     * \n     * @protected\n     * @method module:util/media/media._$$Media#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        this._$stop();\n    };\n    /**\n     * 执行播放操作\n     * \n     * @protected\n     * @method module:util/media/media._$$Media#__doPlay\n     * @return {Void}\n     */\n    _pro.__doPlay = _f;\n    /**\n     * 执行暂停操作\n     * \n     * @protected\n     * @method module:util/media/media._$$Media#__doPause\n     * @return {Void}\n     */\n    _pro.__doPause = _f;\n    /**\n     * 执行停止操作\n     * \n     * @protected\n     * @method module:util/media/media._$$Media#__doStop\n     * @return {Void}\n     */\n    _pro.__doStop = _f;\n    /**\n     * 播放停止触发事件\n     * \n     * @protected\n     * @method module:util/media/media._$$Media#__onStop\n     * @return {Void}\n     */\n    _pro.__onStop = function(){\n        this.__doStateChange(4);\n        this.__doStateChange(0);\n    };\n    /**\n     * 播放错误\n     *\n     * @protected\n     * @method module:util/media/media._$$Media#__doError\n     * @return {Void}\n     */\n    _pro.__doError = function(){\n        this.__state = 0;\n    };\n    /**\n     * 设置播放时间\n     * \n     * @abstract\n     * @method module:util/media/media._$$Media#__setCurrentTime\n     * @return {Void}\n     */\n    _pro.__setCurrentTime = _f;\n    /**\n     * 获取播放时间\n     * \n     * @abstract\n     * @method module:util/media/media._$$Media#__getCurrentTime\n     * @return {Number} 当前时间\n     */\n    _pro.__getCurrentTime = _f;\n    /**\n     * 设置音量\n     * \n     * @abstract\n     * @method module:util/media/media._$$Media#__setVolume\n     * @return {Void}\n     */\n    _pro.__setVolume = _f;\n    /**\n     * 获取音量\n     * \n     * @abstract\n     * @method module:util/media/media._$$Media#__getVolume\n     * @return {Number} 音量\n     */\n    _pro.__getVolume = _f;\n    /**\n     * 修改媒体播放状态\n     * \n     * @protected\n     * @method module:util/media/media._$$Media#__doStateChange\n     * @param  {Number} arg0 - 播放状态\n     * @return {Void}\n     */\n    _pro.__doStateChange = function(_state){\n        if (_state==this.__state) return;\n        this.__state = _state;\n        this._$dispatchEvent(\n            'onstatechange',{\n                state:this.__state\n            }\n        );\n    };\n    /**\n     * 音量变化触发事件\n     * \n     * @protected\n     * @method module:util/media/media._$$Media#__onVolumeChange\n     * @return {Void}\n     */\n    _pro.__onVolumeChange = function(){\n        this._$dispatchEvent(\n            'onvolumechange',{\n                volume:this._$volume()\n            }\n        );\n    };\n    /**\n     * 取媒体总时长\n     * \n     * @method module:util/media/media._$$Media#_$duration\n     * @return {Number} 媒体总时长\n     */\n    _pro._$duration = _f;\n    /**\n     * 更新多媒体文件地址\n     * \n     * @method module:util/media/media._$$Media#_$source\n     * @param  {String} arg0 - 文件地址\n     * @return {Void}\n     */\n    _pro._$source = function(_url){\n        _url = _url||'';\n        if (!_url) return;\n        this._$stop();\n        this.__source = _url;\n    };\n    /**\n     * 播放\n     * \n     * @method module:util/media/media._$$Media#_$play\n     * @return {Void}\n     */\n    _pro._$play = function(){\n        // only stop and pause can do play\n        if (this.__state==0||this.__state==3){\n            this.__doPlay();\n        }\n    };\n    /**\n     * 暂停\n     * \n     * @method module:util/media/media._$$Media#_$pause\n     * @return {Void}\n     */\n    _pro._$pause = function(){\n        // only buffer and play can do pause\n        if (this.__state==1||this.__state==2){\n            this.__doPause();\n        }\n    };\n    /**\n     * 停止\n     * \n     * @method module:util/media/media._$$Media#_$stop\n     * @return {Void}\n     */\n    _pro._$stop = function(){\n        // only buffer,play and pause can do stop\n        if (this.__state!=0){\n            this.__doStop();\n        }\n    };\n    /**\n     * 定位到播放位置\n     * \n     * @method module:util/media/media._$$Media#_$seek\n     * @param  {Number} arg0 - 播放时间，不传此参数表示获取播放时间\n     * @return {Number}        播放时间\n     */\n    _pro._$seek = function(_time){\n        if (_time!=null){\n            this.__setCurrentTime(_time);\n        }\n        return this.__getCurrentTime();\n    };\n    /**\n     * 设置/获取音量\n     * \n     * @method module:util/media/media._$$Media#_$volume\n     * @param  {Number} arg0 - 音量大小，0-100之间的数值，不传此参数表示获取音量值\n     * @return {Number}        音量大小，0-100之间的数值\n     */\n    _pro._$volume = function(_volume){\n        if (_volume!=null){\n            var _volume = Math.max(0,Math.min(_volume,100));\n            this.__setVolume(_volume/100);\n        }\n        return this.__getVolume()*100;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej,ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/media/playlist.js",
    "content": "/*\n * ------------------------------------------\n * 多媒体播放列表管理控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/media/playlist */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    'util/event'\n],function(NEJ,_k,_u,_t,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 多媒体播放列表管理控件\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/media/playlist'\n     * ],function(_t){\n     *     var _playlist = _t._$$PlayList._$allocate({\n     *         mode:1,\n     *         list:[{id:1,url:'a.mp3'},...],\n     *         onmodechange:function(_event){\n     *             console.log(_event.mode);\n     *             // TODO 同步UI状态\n     *         },\n     *         onmediachange:function(_event){\n     *             console.log(_event.list[_event.index]);\n     *             // TODO 同步播放歌曲\n     *         }\n     *     });\n     *     // 下一首\n     *     _playlist._$next();\n     *     // 上一首\n     *     _playlist._$prev();\n     *     // 修改播放模式\n     *     _playlist._$setPlayMode(2);\n     * });\n     * ```\n     *\n     * @class    module:util/media/playlist._$$PlayList\n     * @extends  module:util/event._$$EventTarget\n     *\n     * @param    {Object} config - 可选配置参数\n     * @property {Array}  list   - 多媒体列表\n     * @property {Number} mode   - 播放模式\n     */\n    /**\n     * 当前媒体变化事件\n     * \n     * @event    module:util/media/playlist._$$PlayList#onmediachange\n     * @param    {Object}  event - 媒体信息\n     * @property {Number}  index - 当前媒体索引\n     * @property {Number}  last  - 上一个媒体索引\n     * @property {Array}   list  - 播放列表\n     */\n    /**\n     * 多媒体追加触发事件，如果处理过程中将data置空则不追加\n     * \n     * @event    module:util/media/playlist._$$PlayList#onbeforeappend\n     * @param    {Object}   event - 媒体信息\n     * @property {Variable} data  - 媒体对象\n     * @property {Array}    list  - 播放列表\n     * @property {Number}   index - 当前媒体索引\n     */\n    /**\n     * 播放模式变化事件\n     * \n     * @event    module:util/media/playlist._$$PlayList#onmodechange\n     * @param    {Object} event - 模式信息\n     * @property {Number} mode  - 当前播放模式\n     * @property {Number} last  - 上一个播放模式\n     */\n    _p._$$PlayList = _k._$klass();\n    _pro = _p._$$PlayList._$extend(_t._$$EventTarget);\n    /**\n     * 重置控件\n     * \n     * @protected\n     * @method module:util/media/playlist._$$PlayList#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this._$setPlayMode(_options.mode);\n        this._$setPlayList(_options.list);\n    };\n    /**\n     * 销毁控件\n     * \n     * @protected\n     * @method module:util/media/playlist._$$PlayList#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__index;\n        delete this.__list;\n        delete this.__mode;\n        delete this.__rlist;\n    };\n    /**\n     * 生成随机列表，子类可重写随机列表生成规则\n     * \n     * @protected\n     * @method module:util/media/playlist._$$PlayList#__doGenRandList\n     * @return {Void}\n     */\n    _pro.__doGenRandList = (function(){\n        var _default = function(_value,_dft){\n            return _value==null?_dft:_value;\n        };\n        return function(){\n            if (!this.__list||!this.__list.length){\n                this.__rlist = [];\n                return;\n            }\n            var _result = [0],_ptr1,_tmp0,\n                _ptr0 = this.__list.length;\n            while(_ptr0>1){\n                _ptr1 = Math.floor(Math.random()*_ptr0);\n                _ptr0--;\n                if (_ptr0!==_ptr1){\n                    _tmp = _default(_result[_ptr0],_ptr0);\n                    _result[_ptr0] = _default(_result[_ptr1],_ptr1);\n                    _result[_ptr1] = _tmp;\n                }else{\n                    // fill result\n                    _result[_ptr0] = _default(_result[_ptr0],_ptr0);\n                }\n            }\n            this.__rlist = _result;\n        };\n    })();\n    /**\n     * 设置播放模式，非法输入均使用列表循环模式，可用模式值\n     * \n     * | 值   |   描述 |\n     * | :--- | :--- |\n     * | 0    |   列表循环【默认】 |\n     * | 1    |   单曲循环 |\n     * | 2    |   随机播放 |\n     * \n     * @method module:util/media/playlist._$$PlayList#_$setPlayMode\n     * @param  {Number} arg0 - 播放模式\n     * @return {Void}\n     */\n    _pro._$setPlayMode = function(_mode){\n        // check mode\n        _mode = parseInt(_mode)||0;\n        if (_mode<0||_mode>2){\n            _mode = 0;\n        }\n        if (_mode===this.__mode) return;\n        // save mode\n        var _event = {\n            mode:_mode,\n            last:this.__mode\n        };\n        this.__mode = _mode;\n        // for rand mode\n        if (this.__mode==2){\n            this.__doGenRandList();\n        }else{\n            delete this.__rlist;\n        }\n        this._$dispatchEvent('onmodechange',_event);\n    };\n    /**\n     * 获取播放模式\n     * \n     * @method module:util/media/playlist._$$PlayList#_$getPlayMode\n     * @see    module:util/media/playlist._$$PlayList#_$setPlayMode\n     * @return {Number} 播放模式\n     */\n    _pro._$getPlayMode = function(){\n        return this.__mode;\n    };\n    /**\n     * 设置前播放列表\n     * \n     * @method module:util/media/playlist._$$PlayList#_$setPlayList\n     * @param  {Array} arg0 - 媒体列表\n     * @return {Void}\n     */\n    _pro._$setPlayList = function(_list){\n        if (!_u._$isArray(_list)){\n            _list = [];\n        }\n        this.__list = _list;\n        // replay after list change\n        if (this.__mode==2){\n            this.__doGenRandList();\n            this.__index = this.__rlist[0];\n        }else{\n            this.__index = 0;\n        }\n        this._$play();\n    };\n    /**\n     * 取当前播放列表\n     * \n     * @method module:util/media/playlist._$$PlayList#_$getPlayList\n     * @return {Array} 媒体列表\n     */\n    _pro._$getPlayList = function(){\n        return this.__list;\n    };\n    /**\n     * 设置播放歌曲索引，没有播放列表或者索引值越界均不做任何处理\n     * \n     * @method module:util/media/playlist._$$PlayList#_$setPlayIndex\n     * @param  {Number} arg0 - 歌曲索引\n     * @return {Void}\n     */\n    _pro._$setPlayIndex = function(_index){\n        // check playlist and index\n        var _length = this.__list.length;\n        _index = parseInt(_index);\n        var _current = _index,\n            _last = this.__index;\n        if (_index<0||_index>=_length){\n            _current = -1;\n        }else{\n            // save index\n            this.__index = _index;\n        }\n        // onmediachange\n        var _event = {\n            last:_last,\n            index:_current,\n            list:this.__list\n        };\n        this._$dispatchEvent('onmediachange',_event);\n    };\n    /**\n     * 获取播放歌曲索引\n     * \n     * @method module:util/media/playlist._$$PlayList#_$getPlayIndex\n     * @return {Number} 歌曲索引\n     */\n    _pro._$getPlayIndex = function(){\n        return this.__index;\n    };\n    /**\n     * 追加多媒体项\n     * \n     * @method module:util/media/playlist._$$PlayList#_$appendMedia\n     * @param  {Variable} arg0 - 多媒体项\n     * @return {Void}\n     */\n    _pro._$appendMedia = function(_media){\n        var _event = {\n            data:_media,\n            list:this.__list,\n            index:this.__index\n        };\n        // for media filter\n        this._$dispatchEvent('onbeforeappend',_event);\n        _media = _event.data;\n        if (!!_media){\n            this.__list.push(_media);\n            if (this.__mode==2){\n                this.__doGenRandList();\n            }\n        }\n        this._$dispatchEvent('onafterappend',_event);\n    };\n    /**\n     * 删除多媒体项，索引值越界不做任何处理\n     * \n     * @method module:util/media/playlist._$$PlayList#_$removeMedia\n     * @param  {Number} arg0 - 媒体索引\n     * @return {Void}\n     */\n    _pro._$removeMedia = function(_index){\n        var _length = this.__list.length;\n        if (_index<0||_index>=_legnth) return;\n        this.__list.splice(_index,1);\n        // re-gen rand list\n        if (this.__mode==2){\n            this.__doGenRandList();\n        }\n        // remove current media\n        if(_index==this.__index){\n            if (this.__index>=_length){\n                this.__index = _length-1;\n            }\n            this._$play();\n        }\n    };\n    /**\n     * 播放指定偏移量的歌曲\n     * \n     * @method module:util/media/playlist._$$PlayList#_$play\n     * @param  {Number} arg0 - 索引偏移量，可以为0，正数，负数\n     * @return {Void}\n     */\n    _pro._$play = (function(){\n        var _loop = function(_delta){\n            var _length = this.__list.length,\n                _index = (this.__index+_delta)%_length;\n            return _index<0?(_length+_index):_index;\n        };\n        var _rand = function(_delta){\n            var _length = this.__list.length,\n                _index = _u._$indexOf(\n                    this.__rlist,this.__index\n                );\n            _index = (_index+_delta)%_length;\n            _index = _index<0?(_length+_index):_index;\n            return this.__rlist[_index];\n        };\n        var _fmap = [_loop,_loop,_rand];\n        return function(_delta){\n            _delta = parseInt(_delta)||0;\n            this._$setPlayIndex(\n                (_fmap[this.__mode]||_f).call(this,_delta)||0\n            );\n        };\n    })();\n    /**\n     * 自动播放下一首歌曲\n     * \n     * @method module:util/media/playlist._$$PlayList#_$autoNext\n     * @return {Void}\n     */\n    _pro._$autoNext = function(){\n        if (this.__mode==1){\n            this._$setPlayIndex(\n                this._$getPlayIndex()\n            );\n        }else{\n            this._$next();\n        }\n    };\n    /**\n     * 播放下一首歌曲\n     * \n     * @method module:util/media/playlist._$$PlayList#_$next\n     * @return {Void}\n     */\n    _pro._$next = function(){\n        this._$play(1);\n    };\n    /**\n     * 播放上一首歌曲\n     * \n     * @method module:util/media/playlist._$$PlayList#_$prev\n     * @return {Void}\n     */\n    _pro._$prev = function(){\n        this._$play(-1);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej,ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/media/test/audio.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>audio测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit audio test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n\t\t<div id=\"audio-box\"></div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./audio.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/media/test/audio.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"audio\");\n    \n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v'),\n        _p = _('nej.ut');\n    \n    test('audio',function(){\n        expect(0);\n\t\tvar _mda = _p._$$MediaAudio._$allocate({\n\t\t\tpreload:false,\n\t\t\turl:'http://www.zhlongyin.com/UploadFiles/xrxz/2011/5/201105051307513619.mp3',\n\t\t\tonstatechange:function(_event){\n\t\t\t}\n\t\t});\n\t\t_mda = _p._$$MediaAudio._$recycle(_mda);\n\t\t_mda = _p._$$MediaAudio._$allocate({\n            preload:false,\n            url:'http://www.zhlongyin.com/UploadFiles/xrxz/2011/5/201105051307513619.mp3',\n            onstatechange:function(_event){\n            }\n        });\n\t\t_mda = _p._$$MediaAudio._$recycle(_mda);\n        _mda = _p._$$MediaAudio._$allocate({\n            preload:false,\n            url:'http://www.zhlongyin.com/UploadFiles/xrxz/2011/5/201105051307513619.mp3',\n            onstatechange:function(_event){\n            }\n        });\n\t\t_mda._$play();\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}audio.test.js',\n    ['{lib}util/media/audio.js'],f);\n});\n  "
  },
  {
    "path": "src/util/page/base.js",
    "content": "/*\n * ------------------------------------------\n * 分页逻辑基类封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/page/base */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    'base/element',\n    'base/event',\n    'util/event'\n],function(NEJ,_k,_u,_e,_v,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 分页逻辑封装基类\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"page\">\n     *   <a href=\"#\" class=\"zbtn sbtn\">首页</a>\n     *   <a href=\"#\" class=\"zbtn zprv\">上一页</a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zbtn znxt\">下一页</a>\n     *   <a href=\"#\" class=\"zbtn ebtn\">末页</a>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/klass',\n     *     'base/util',\n     *     'util/page/base'\n     * ],function(_k,_u,_t,_p,_o,_f,_r){\n     *     var _pro;\n     *     \n     *     // 首先继承此基类，重写__doRefreshPage方法\n     *     _p._$$PageSimple = _k._$klass();\n     *     _pro = _p._$$PageSimple._$extend(_t._$$PageAbstract);\n     *     \n     *     // 刷新页码列表算法\n     *     _pro.__doRefreshPage = function(){\n     *         var _length = this.__list.length;\n     *         if (!_length) return;\n     *         var _middle = Math.floor(_length/2),\n     *             _offset = Math.min(this.__total-_length+1,\n     *                       Math.max(1,this.__index-_middle));\n     *         _u._$forEach(\n     *             this.__list,function(_node,_index){\n     *                 var _page = _offset+_index;\n     *                 this.__doSetNodeIndex(\n     *                     _node,\n     *                     _page>this.__total?null:_page\n     *                 );\n     *             },this\n     *         );\n     *     };\n     *     \n     *     return _p;\n     * })\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/element',\n     *     '/path/to/custom/page.js'\n     * ],function(_e,_t,_p,_o,_f,_r){\n     * \n     *     // 第二步，生成simplePage的实例\n     *     var _list = _e._$getChildren('page');\n     *     var _page = _t._$$PageSimple._$allocate({\n     *         list:_e._$getByClassName('page','zpgi'),\n     *         event:'click',\n     *         pbtn:_list[1],\n     *         nbtn:_list[11],\n     *         sbtn:_list[0],\n     *         ebtn:_list[12],\n     *         index:90,\n     *         total:100,\n     *         onchange:function(_obj){\n     *         // 返回页码信息，last:上一次页面,\n     *            index:当前页面，total:总页数\n     *         }\n     *     });\n     *     \n     *     // 第三步，可以调用提供的共有接口\n     *     _page._$setTotal(100);\n     * })\n     * ```\n     * \n     * @class    module:util/page/base._$$PageAbstract\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object}      config   - 可选配置参数\n     * @property {Array}       list     - 页码节点列表【长度保持奇数】\n     * @property {String}      event    - 触发页码切换事件，默认为click\n     * @property {String|Node} pbtn     - 上一页按钮\n     * @property {String|Node} nbtn     - 下一页按钮\n     * @property {String|Node} sbtn     - 首页按钮\n     * @property {String|Node} ebtn     - 尾页按钮\n     * @property {Number}      index    - 当前页码\n     * @property {Number}      total    - 总页码数\n     * @property {Number}      limit    - 总页数限制\n     * @property {Boolean}     parented - 选中样式是否在父节点\n     * @property {String}      selected - 选中样式，默认为js-selected\n     * @property {String}      disabled - 禁用样式，默认为js-disabled\n     */\n    /**\n     * 页码变化触发事件，输入{last:3,index:1,total:12}\n     * \n     * @event    module:util/page/base._$$PageAbstract#onchange\n     * @param    {Object} event - 页码信息\n     * @property {Number} last  - 上一次的页码\n     * @property {Number} index - 当前要切换的页面\n     * @property {Number} total - 总页面数\n     */\n    _p._$$PageAbstract = _k._$klass();\n    _pro = _p._$$PageAbstract._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/page/base._$$PageAbstract#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__pbtn  = _options.pbtn;\n        this.__nbtn  = _options.nbtn;\n        this.__sbtn  = _options.sbtn;\n        this.__ebtn  = _options.ebtn;\n        this.__name  = _options.event||'click';\n        this.__parented = !!_options.parented;\n        this.__selected = _options.selected||'js-selected';\n        this.__disabled = _options.disabled||'js-disabled';\n        this.__doPageListCheck(_options.list);\n        this.__limit = _options.limit||Infinity;\n        this._$updatePage(\n            _options.index||1,\n            _options.total||1\n        );\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/page/base._$$PageAbstract#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__list;\n        delete this.__name;\n        delete this.__pbtn;\n        delete this.__nbtn;\n        delete this.__sbtn;\n        delete this.__ebtn;\n        delete this.__last;\n        delete this.__total;\n        delete this.__index;\n        delete this.__extdata;\n        delete this.__selected;\n        delete this.__disabled;\n    };\n    /**\n     * 取选中样式所在节点\n     * \n     * @protected\n     * @method module:util/page/base._$$PageAbstract#__getSelectNode\n     * @param  {Node} arg0 - 页码节点\n     * @return {Node}        选中样式作用节点\n     */\n    _pro.__getSelectNode = function(_node){\n        return !this.__parented?_node:_node.parentNode;\n    };\n    /**\n     * 检查页码列表节点\n     * \n     * @protected\n     * @method module:util/page/base._$$PageAbstract#__doPageListCheck\n     * @param  {Array} arg0 - 列表节点\n     * @return {Void}\n     */\n    _pro.__doPageListCheck = (function(){\n        var _doInitDomEvent = function(_node){\n            this.__list.push(_node);\n            this.__doInitDomEvent([[\n                 _node,this.__name,this.\n                 __onClick._$bind2(this,0)\n            ]]);\n        };\n        return function(_list){\n            this.__list = [];\n            this.__doInitDomEvent([[\n                this.__pbtn,'click',\n                this.__onClick._$bind2(this,-1)\n            ],[\n                this.__nbtn,'click',\n                this.__onClick._$bind2(this, 1)\n            ],[\n                this.__sbtn,'click',\n                this.__onClick._$bind2(this,-2)\n            ],[\n                this.__ebtn,'click',\n                this.__onClick._$bind2(this, 2)\n            ]]);\n            _u._$forEach(_list,_doInitDomEvent,this);\n        };\n    })();\n    /**\n     * 设置节点的页码值\n     * \n     * @protected\n     * @method module:util/page/base._$$PageAbstract#__doSetNodeIndex\n     * @param  {Node}   arg0 - 页码节点\n     * @param  {Number} arg1 - 页码值\n     * @return {Void}\n     */\n    _pro.__doSetNodeIndex = function(_node,_index){\n        var _parent = this.__getSelectNode(_node);\n        if (_index==null){\n            _node.innerText = '';\n            _e._$setStyle(_node,'display','none');\n            _e._$delClassName(_parent,this.__selected);\n        }else{\n            _node.innerText = _index;\n            _e._$setStyle(_node,'display','');\n            _index==this.__index\n            ? _e._$addClassName(_parent,this.__selected)\n            : _e._$delClassName(_parent,this.__selected);\n        }\n    };\n    /**\n     * 同步按钮状态\n     * \n     * @protected\n     * @method module:util/page/base._$$PageAbstract#__doSyncBtnState\n     * @return {Void}\n     */\n    _pro.__doSyncBtnState = function(){\n        // sync start and previous\n        if (this.__index<=1){\n            _e._$addClassName(this.__pbtn,this.__disabled);\n            _e._$addClassName(this.__sbtn,this.__disabled);\n        }else{\n            _e._$delClassName(this.__pbtn,this.__disabled);\n            _e._$delClassName(this.__sbtn,this.__disabled);\n        }\n        // sync end and next\n        if (this.__index>=this.__total){\n            _e._$addClassName(this.__nbtn,this.__disabled);\n            _e._$addClassName(this.__ebtn,this.__disabled);\n        }else{\n            _e._$delClassName(this.__nbtn,this.__disabled);\n            _e._$delClassName(this.__ebtn,this.__disabled);\n        }\n    };\n    /**\n     * 刷新页码列表算法\n     * \n     * @protected\n     * @method module:util/page/base._$$PageAbstract#__doRefreshPage\n     * @return {Void}\n     */\n    _pro.__doRefreshPage = _f;\n    /**\n     * 强制刷新至新页码\n     * \n     * @protected\n     * @method module:util/page/base._$$PageAbstract#__doChangeIndex\n     * @return {Void}\n     */\n    _pro.__doChangeIndex = function(){\n        this.__doRefreshPage();\n        this.__doSyncBtnState();\n        this._$dispatchEvent(\n            'onchange',{\n                last:this.__last,\n                total:this.__total,\n                index:this.__index,\n                ext:this.__extdata\n            }\n        );\n    };\n    /**\n     * 保存当前页码\n     * \n     * @protected\n     * @method module:util/page/base._$$PageAbstract#__doSaveIndex\n     * @param  {Number}  arg0 - 页码\n     * @return {Boolean}        是否保存成功\n     */\n    _pro.__doSaveIndex = function(_index){\n        _index = parseInt(_index);\n        if (isNaN(_index)||\n            this.__total==null)\n            return !1;\n        _index = Math.max(1,Math.min\n                (_index,this.__total));\n        this.__last  = this.__index;\n        this.__index = _index;\n        return !0;\n    };\n    /**\n     * 保存总页码\n     * \n     * @protected\n     * @method module:util/page/base._$$PageAbstract#__doSaveTotal\n     * @param  {Number}  arg0 - 总页码\n     * @return {Boolean}        页码是否保存成功\n     */\n    _pro.__doSaveTotal = function(_total){\n        _total = parseInt(_total);\n        if (isNaN(_total)||_total<1)\n            return !1;\n        this.__total = Math.min(\n            _total,this.__limit\n        );\n        return !0;\n    };\n    /**\n     * 触发点击事件\n     * \n     * @protected\n     * @method module:util/page/base._$$PageAbstract#__onClick\n     * @param  {Event}  arg0 - 事件对象\n     * @param  {Number} arg1 - 页码标记\n     * @return {Void}\n     */\n    _pro.__onClick = function(_event,_flag){\n        _v._$stopDefault(_event);\n        // check state\n        var _element = _v._$getElement(_event),\n            _selected = _e._$hasClassName(\n                this.__getSelectNode(_element\n            ),this.__selected),\n            _disabled = _e._$hasClassName(_element,this.__disabled);\n        if (!_element||_selected||_disabled){\n            return;\n        }\n        // update index\n        var _index = _element.innerText;\n        switch(_flag){\n            // previous or next\n            case  1:\n            case -1:\n                _index = this.__index+_flag;\n            break;\n            // end\n            case  2:\n                _index = this.__total;\n            break;\n            // start\n            case -2:\n                _index = 1;\n            break;\n        }\n        this._$setIndex(_index);\n    };\n    /**\n     * 返回当前页码数\n     * \n     * 脚本举例\n     * ```javascript\n     * // 获取当前页码\n     * var _index = _page._$getIndex();\n     * ```\n     * \n     * @method module:util/page/base._$$PageAbstract#_$getIndex\n     * @return {Number} 当前页码\n     */\n    _pro._$getIndex = function(){\n        return this.__index;\n    };\n    /**\n     * 跳转至指定页码\n     * \n     * 脚本举例\n     * ```javascript\n     * // 设置当前页码\n     * _page._$setIndex(2);\n     * ```\n     * \n     * @method module:util/page/base._$$PageAbstract#_$setIndex\n     * @param  {Number} arg0 - 页码值\n     * @return {Void}\n     */\n    _pro._$setIndex = function(_index){\n        var _oidx = this.__index;\n        this.__doSaveIndex(_index);\n        if (_oidx!=this.__index){\n            this.__doChangeIndex();\n        }\n    };\n     /**\n     * 返回页码总数\n     * \n     * 脚本举例\n     * ```javascript\n     * // 获取总页码数\n     * var _total = _page._$getTotal();\n     * ```\n     * \n     * @method module:util/page/base._$$PageAbstract#_$getTotal\n     * @return {Number} 页码总数\n     */\n    _pro._$getTotal = function(){\n        return this.__total;\n    };\n    /**\n     * 设置总页码数，当前页码重置为首页\n     * \n     * 脚本举例\n     * ```javascript\n     * // 设置总页码数\n     * _page._$setTotal(10);\n     * ```\n     * \n     * @method module:util/page/base._$$PageAbstract#_$setTotal\n     * @param  {Number} arg0 - 总页码数\n     * @return {Void}\n     */\n    _pro._$setTotal = function(_total){\n        if (this.__doSaveTotal(_total)&&\n            this.__index!=null){\n            this.__index = 1;\n            this.__doChangeIndex();\n        }\n    };\n    /**\n     * 更新总页码数，当前页码不变，无回调\n     * \n     * 脚本举例\n     * ```javascript\n     * // 设置总页码数\n     * _page._$updateTotal(10);\n     * ```\n     * \n     * @method module:util/page/base._$$PageAbstract#_$updateTotal\n     * @param  {Number} arg0 - 总页码数\n     * @return {Void}\n     */\n    _pro._$updateTotal = function(_total){\n        if (this.__doSaveTotal(_total)){\n            this.__doRefreshPage();\n            this.__doSyncBtnState();\n        }\n    };\n    /**\n     * 更新页码信息\n     * \n     * 脚本举例\n     * ```javascript\n     * // 设置总页码数，并且跳转到指定页面\n     * _page._$updatePage(2,10);\n     * ```\n     * \n     * @method module:util/page/base._$$PageAbstract#_$updatePage\n     * @param  {Number} arg0 - 当前页码\n     * @param  {Number} arg1 - 总页码数\n     * @return {Void}\n     */\n    _pro._$updatePage = function(_index,_total){\n        if (!this.__doSaveTotal(_total)||\n            !this.__doSaveIndex(_index))\n            return;\n        this.__doChangeIndex();\n    };\n\n    if (CMPT){\n        NEJ.P('nej.ut')._$$AbstractPage = _p._$$PageAbstract;\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/page/page.base.js",
    "content": "// link to util/page/base for compatible\n// use util/page/base for new project\nNEJ.define(['./base.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/page/page.js",
    "content": "/*\n * ------------------------------------------\n * 三段分页器业务逻辑封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/page/page */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/util',\n    './base.js'\n],function(NEJ,_k,_e,_u,_t,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 三段分页器业务逻辑封装，适合于以下形式的分页器\n     * \n     * 此结构没有首页，末页，因为首页，末页都可点击\n     * \n     * ```\n     *     ____      _       _   _   _   _   _       ___    ____\n     *    |上一页|  |1| ... |5| |6| |7| |8| |9| ... |100|  |下一页|\n     *     ----      -       -   -   -   -   -       ---    ----\n     * ```\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"pagebox\">\n     *   <a href=\"#\" class=\"zbtn zprv\">上一页</a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zbtn znxt\">下一页</a>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/element',\n     *     'util/page/page'\n     * ],function(_e,_t,_p,_o,_f,_r){\n     *     var _page  = _t._$$PageFragment._$allocate({\n     *         parent:'pagebox',\n     *         event:'click',\n     *         index:9,\n     *         total:10,\n     *         onchange:function(_event){\n     *             // 返回页码信息，last:上一次页面,index:当前页面，total:总页数\n     *         }\n     *     });\n     *     \n     *     // 翻到第4页\n     *     _page._$setIndex(4);\n     *     // 改变总页数,状态复原到第一页\n     *     _page._$getTotal(20);\n     *     // 想要保持页面信息状态\n     *     _page._$updatePage(5,10);\n     * })\n     * ```\n     * \n     * @class    module:util/page/page._$$PageFragment\n     * @extends  module:util/page/base._$$PageAbstract\n     * \n     * @param    {Object}      config   - 可选配置参数\n     * @property {Array}       list     - 页码节点列表【长度保持奇数】\n     * @property {String}      event    - 触发页码切换事件，默认为click\n     * @property {String|Node} pbtn     - 上一页按钮\n     * @property {String|Node} nbtn     - 下一页按钮\n     * @property {String|Node} sbtn     - 首页按钮\n     * @property {String|Node} ebtn     - 尾页按钮\n     * @property {Number}      index    - 当前页码\n     * @property {Number}      total    - 总页码数\n     * @property {String}      selected - 选中样式，默认为js-selected\n     * @property {String}      disabled - 禁用样式，默认为js-disabled\n     */\n    _p._$$PageFragment = _k._$klass();\n    _pro = _p._$$PageFragment._$extend(_t._$$PageAbstract);\n    /**\n     * 初始化控件\n     * \n     * @protected\n     * @method module:util/page/page._$$PageFragment#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__ndot = [];\n        this.__super();\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/page/page._$$PageFragment#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        this.__doRecycleDotNode();\n    };\n    /**\n     * 回收省略节点\n     * \n     * @protected\n     * @method module:util/page/page._$$PageFragment#__doRecycleDotNode\n     * @return {Void}\n     */\n    _pro.__doRecycleDotNode = (function(){\n        var _doRecycle = function(_node,_index,_list){\n            _e._$remove(_node);\n            _list.splice(_index,1);\n        };\n        return function(){\n            _u._$reverseEach(\n                this.__ndot,_doRecycle\n            );\n        };\n    })();\n    /**\n     * 刷新页码列表算法\n     * \n     * @protected\n     * @method module:util/page/page._$$PageFragment#__doRefreshPage\n     * @return {Void}\n     */\n    _pro.__doRefreshPage = function(){\n        this.__extdata = {\n            last:!1,\n            first:!1,\n            list:this.__list\n        };\n        this.__doRecycleDotNode();\n        this.__doSetNodeIndex(this.__list[0],1);\n        // for total<length\n        var _point = 1,\n            _length = this.__list.length;\n        if (this.__total<_length){\n            for(var _page;_point<_length;_point++){\n                _page = _point+1;\n                this.__doSetNodeIndex(\n                    this.__list[_point],\n                    _page>this.__total?null:_page\n                );\n            }\n            return;\n        }\n        // 2 -> index\n        if (this.__index>1){\n            var _count = Math.floor((_length-2)/2),\n                _mxbeg = this.__total-_length+2,\n                _start = Math.max(2,this.__index-_count);\n            if (this.__total>=_length){\n                _start = Math.min(_start,_mxbeg);\n            }\n            if (_start>2){\n                var _node = _e._$create('span','zdot');\n                this.__ndot.push(_node);\n                _node.innerText = '...';\n                this.__list[0].insertAdjacentElement(\n                    'afterEnd',_node\n                );\n                this.__extdata.first = !0;\n            }\n            for(var _index;;_point++){\n                _index = _start+_point-1;\n                if (_index>this.__index)\n                    break;\n                this.__doSetNodeIndex(\n                    this.__list[_point],_index\n                );\n            }\n        }\n        // index -> total\n        if (this.__index<this.__total){\n            var _index,_start = this.__index+1;\n            for(var i=0,l=_length-2;;i++,_point++){\n                _index = _start+i;\n                if (_point>l||_index>this.__total)\n                    break;\n                this.__doSetNodeIndex(\n                    this.__list[_point],_index\n                );\n            }\n            if (_index<this.__total){\n                var _node = _e._$create('span','zdot');\n                this.__ndot.push(_node);\n                _node.innerText = '...';\n                this.__list[_point].insertAdjacentElement(\n                    'beforeBegin',_node\n                );\n                this.__extdata.last = !0;\n            }\n            if (_index<=this.__total){\n                this.__doSetNodeIndex(\n                    this.__list[_point++],\n                    this.__total\n                );\n            }\n        }\n        // hidden point -> length\n        for(;_point<_length;_point++){\n            this.__doSetNodeIndex(this.__list[_point]);\n        }\n    };\n\n    if (CMPT){\n        NEJ.P('nej.ut')._$$Page = _p._$$PageFragment;\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/page/page.simple.js",
    "content": "// link to util/page/simple for compatible\n// use util/page/simple for new project\nNEJ.define(['./simple.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/page/simple.js",
    "content": "/*\n * ------------------------------------------\n * 一段分页器业务逻辑封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/page/simple */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/util',\n    './base.js'\n],function(NEJ,_k,_u,_t,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 一段分页器业务逻辑封装，主要适合于以下形式的分页器\n     * \n     * 此结构有首页，末页\n     * \n     * ```\n     *      ___   ____    _   _   _   __   __   ____   ___\n     *     |首页| |上一页|  |7| |8| |9| |10| |11| |下一页| |尾页|\n     *      ---   ----    -   -   -   --   --   ----   ---\n     * ```\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"page\">\n     *   <a href=\"#\" class=\"zbtn sbtn\">首页</a>\n     *   <a href=\"#\" class=\"zbtn zprv\">上一页</a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zpgi\"></a>\n     *   <a href=\"#\" class=\"zbtn znxt\">下一页</a>\n     *   <a href=\"#\" class=\"zbtn ebtn\">末页</a>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/page/simple',\n     *     'base/element'\n     * ],function(_t,_e,_p,_o,_f,_r){\n     *     var _list = _e._$getChildren('page');\n     *     var _page = _t._$$PageSimple._$allocate({\n     *         list:_e._$getByClassName('page','zpgi'),\n     *         event:'click',\n     *         pbtn:_list[1],\n     *         nbtn:_list[11],\n     *         sbtn:_list[0],\n     *         ebtn:_list[12],\n     *         index:90,\n     *         total:100,\n     *         onchange:function(_event){\n     *             // 返回页码信息，last:上一次页面,index:当前页面，total:总页数\n     *         }\n     *     });\n     *     \n     *     // 翻到第4页\n     *     _page._$setIndex(4);\n     *     // 改变总页数,状态复原到第一页\n     *     _page._$getTotal(20);\n     *     // 想要保持页面信息状态\n     *     _page._$updatePage(5,10);\n     * });\n     * ```\n     * \n     * @class    module:util/page/simple._$$PageSimple\n     * @extends  module:util/page/base._$$PageAbstract\n     * \n     * @param    {Object}      config   - 可选配置参数\n     * @property {Array}       list     - 页码节点列表【长度保持奇数】\n     * @property {String}      event    - 触发页码切换事件，默认为click\n     * @property {String|Node} pbtn     - 上一页按钮\n     * @property {String|Node} nbtn     - 下一页按钮\n     * @property {String|Node} sbtn     - 首页按钮\n     * @property {String|Node} ebtn     - 尾页按钮\n     * @property {Number}      index    - 当前页码\n     * @property {Number}      total    - 总页码数\n     * @property {String}      selected - 选中样式，默认为js-selected\n     * @property {String}      disabled - 禁用样式，默认为js-disabled\n     */\n    _p._$$PageSimple = _k._$klass();\n    _pro = _p._$$PageSimple._$extend(_t._$$PageAbstract);\n    /**\n     * 刷新页码列表算法\n     * \n     * @protected\n     * @method module:util/page/simple._$$PageSimple#__doRefreshPage\n     * @return {Void}\n     */\n    _pro.__doRefreshPage = function(){\n        var _length = this.__list.length;\n        if (!_length) return;\n        var _middle = Math.floor(_length/2),\n            _offset = Math.min(this.__total-_length+1,\n                      Math.max(1,this.__index-_middle));\n        _u._$forEach(this.__list,\n            function(_node,_index){\n                var _page = _offset+_index;\n                this.__doSetNodeIndex(_node,\n                      _page>this.__total||_page<1?null:_page);\n            },this);\n    };\n    /**\n     * 设置是否禁用下一页功能\n     *\n     * @method module:util/page/simple._$$PageSimple#_$disableNext\n     * @param  {Boolean} arg0 - 是否禁用\n     * @return {Void}\n     */\n    _pro._$disableNext = function(_disabled){\n        if (!_disabled){\n            this.__total = Number.MAX_VALUE;\n        }else{\n            this.__total = this.__index;\n        }\n        this.__doSyncBtnState();\n    };\n\n    if (CMPT){\n        NEJ.P('nej.ut')._$$SimplePage = _p._$$PageSimple;\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/placeholder/demo/placeholder.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - Place Holder</title>\n    <meta charset=\"utf-8\" />\n    \n    <style>\n        .abc{background:#fdc;}\n        .js-holder{background:#0000FF;}\n    </style>\n    \n  </head>\n  <body>\n    \n    <p><input type=\"text\" id=\"abc\" placeholder=\"abc\"/></p>\n    <p><textarea id=\"def\" placeholder=\"def\"></textarea></p>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            '../placeholder.js'\n        ],function(_t){\n            _t._$placeholder('abc','js-holder');\n            _t._$placeholder('def','js-holder');\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/placeholder/placeholder.js",
    "content": "/*\n * ------------------------------------------\n * 输入框占位符支持实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/placeholder/placeholder */\nNEJ.define([\n    'base/global',\n    'base/element',\n    'base/chain',\n    '{platform}holder.js'\n],function(NEJ,_e,_x,_h,_p,_o,_f,_r){\n    /**\n     * 输入框占位行为，高版本用placeholder属性和样式处理\n     *\n     * 样式设置占位符文字效果\n     * ```css\n     * input:-moz-placeholder{color:#aaa;font-style:italic;}\n     * input::-ms-input-placeholder{color:#aaa;font-style:italic;}\n     * input::-webkit-input-placeholder{color:#aaa;font-style:italic;}\n     * .js-placeholder{color:#aaa;font-style:italic;}\n     * ```\n     *\n     * 结构举例\n     * ```html\n     * <!-- 使用data-holder属性指定占位文字效果样式名称 -->\n     * <input id=\"abc\" type=\"text\" placeholder=\"text content\" data-holder=\"js-placeholder\"/>\n     * <textarea id=\"abc\" placeholder=\"text content\" data-holder=\"js-placeholder\"></textarea>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/placeholder/placeholder'\n     * ],function(_e){\n     *     // 如果hover效果的样式名已经通过data-holder指定\n     *     _e._$placeholder('abc');\n     *     // 如果样式名没有通过data-holder指定，则可以通过参数输入\n     *     // 当节点有data-holder指定样式名称，同时参数也输入样式名称，则优先使用data-holder指定的样式名\n     *     _e._$placeholder('abc','js-placeholder');\n     * });\n     * ```\n     *\n     * @method module:util/placeholder/placeholder._$placeholder\n     * @param  {String|Node} arg0 - 输入控件，如input、textarea\n     * @param  {String}      arg1 - 占位样式名称，默认为js-placeholder\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$placeholder\n     * @see module:util/placeholder/placeholder._$placeholder\n     */\n    _p._$placeholder = function(_element,_clazz){\n        _element = _e._$get(_element);\n        _h.__setPlaceholder(_element,\n            _e._$dataset(_element,'holder')\n                ||_clazz||'js-placeholder');\n    };\n    // for chainable method\n    _x._$merge(_p);\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.e'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/placeholder/platform/holder.js",
    "content": "/*\n * ------------------------------------------\n * 占位提示接口平台适配实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define(function(_p,_o,_f,_r){\n    /**\n     * 节点占位符行为，高版本浏览器用样式处理\n     * @param  {String|Node} 节点\n     * @param  {String}      样式\n     * @return {Void}\n     */\n    _p.__setPlaceholder = function(_element,_clazz){\n        // do nothing\n    };\n\n    return _p;\n});"
  },
  {
    "path": "src/util/placeholder/platform/holder.patch.js",
    "content": "/*\n * ------------------------------------------\n * 占位提示接口平台适配实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/element',\n\t'base/event',\n\t'base/util',\n\t'base/platform',\n\t'./holder.js'\n],function(_e,_v,_u,_m,_h,_p,_o,_f,_r){\n\t// for ie9-\n\tNEJ.patch('TR<=5.0',function(){\n\t\t/**\n\t\t * 节点占位符行为，高版本浏览器用样式处理\n\t\t * @param  {String|Node} _element 节点\n\t\t * @param  {String}      _clazz   样式\n\t\t * @return {Void}\n\t\t */\n\t\t_h.__setPlaceholder = (function(){\n\t\t    // placeholder flag\n\t\t    var _cache = {},\n\t\t        _ropt = {\n\t\t            nid:'j-holder-'+_u._$uniqueID()\n\t\t        };\n\t\t    // input foucs hide placeholder\n\t\t    var _onFocus = function(_id){\n\t\t        var _input = _e._$get(_id);\n\t\t        _cache[_id] = 2;\n\t\t        if (!!_input.value) return;\n\t\t        _e._$setStyle(\n\t\t            _e._$wrapInline(_input,_ropt),\n\t\t            'display','none'\n\t\t        );\n\t\t    };\n\t\t    // input blur check placeholder show\n\t\t    var _onBlur = function(_id){\n\t\t        var _input = _e._$get(_id);\n\t\t        _cache[_id] = 1;\n\t\t        if (!!_input.value) return;\n\t\t        _e._$setStyle(\n\t\t            _e._$wrapInline(_input,_ropt),\n\t\t            'display',''\n\t\t        );\n\t\t    };\n\t\t    // input value change\n\t\t    var _onInput = function(_id){\n\t\t        var _input = _e._$get(_id);\n\t\t        if (_cache[_id]==2) return;\n\t\t        _e._$setStyle(\n\t\t            _e._$wrapInline(_input,_ropt),\n\t\t            'display',!_input.value?'':'none'\n\t\t        );\n\t\t    };\n\t\t    // wrapper input control\n\t\t    var _doWrapInput = function(_input,_clazz){\n\t\t        var _id = _e._$id(_input),\n\t\t            _label = _e._$wrapInline(_input,{\n\t\t                tag:'label',\n\t\t                clazz:_clazz,\n\t\t                nid:_ropt.nid\n\t\t            });\n\t\t        _label.htmlFor = _id;\n\t\t        var _text = _e._$attr(_input,'placeholder')||'';\n\t\t        _label.innerText = _text=='null'?'':_text;\n\t\t        var _height = _input.offsetHeight+'px';\n\t\t        _e._$style(_label,{\n\t\t            left:0,\n\t\t            // width:_input.offsetWidth+'px',\n\t\t            // height:_height,lineHeight:_height,\n\t\t            display:!_input.value?'':'none'\n\t\t        });\n\t\t    };\n\t\t    return function(_input,_clazz){\n                // has been placeholded\n                if (_cache[_input.id]!=null)\n                    return;\n                _doWrapInput(_input,_clazz);\n\t\t        var _id = _input.id;\n                _cache[_id] = 1;\n                // listen blur and focus event\n                _v._$addEvent(_input,'blur',_onBlur._$bind(null,_id));\n                _v._$addEvent(_input,'focus',_onFocus._$bind(null,_id));\n                _v._$addEvent(_input,'input',_onInput._$bind(null,_id));\n                // IE9 set value hack\n                if (_m._$KERNEL.engine == 'trident' && _m._$KERNEL.release == '5.0'){\n                \t_v._$addEvent(_input,'propertychange',_onInput._$bind(null,_id));\n                }\n        \t};\n\t\t})();\n    });\n\n\treturn _h;\n});"
  },
  {
    "path": "src/util/placeholder/test/placeholder.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>placeholder测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style type=\"text/css\">\n\t\t\t.placeholder input:-moz-placeholder{color:pink;font-style:italic;padding-left:5px;}\n            .placeholder input::-ms-input-placeholder{color:pink;font-style:italic;padding-left:5px;}\n            .placeholder input::-webkit-input-placeholder{color:pink;font-style:italic;padding-left:5px;}\n\t\t\t.placeholder textarea:-moz-placeholder{color:pink;font-style:italic;padding-left:5px;}\n            .placeholder textarea::-ms-input-placeholder{color:pink;font-style:italic;padding-left:5px;}\n            .placeholder textarea::-webkit-input-placeholder{color:pink;font-style:italic;padding-left:5px;}\n            .js-placeholder{color:pink;font-style:italic;padding-left:5px;}\n\t\t\t.zw{color:green;padding-left:5px;}\n\t\t</style>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit placeholder test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n\t\t<div class=\"placeholder\">\n\t        <input id=\"placeholder1\" type=\"text\" placeholder=\"text content\"/>\n            <textarea id=\"placeholder2\" placeholder=\"tetext contenttext contenttext contenttext contenttext contenttext contentxt content\"></textarea>\n\t\t</div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./placeholder.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/placeholder/test/placeholder.test.js",
    "content": "NEJ.define([\n    '{lib}util/placeholder/placeholder.js'\n],function(){\n    //定义测试模块\n    module(\"placeholder\");\n\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v'),\n        _p = _('nej.ut');\n\n    test('placeholder',function(){\n        expect(0);\n        _e._$placeholder('placeholder1','zw');\n        _e._$placeholder('placeholder2','zw');\n    });\n});\n"
  },
  {
    "path": "src/util/profile/profile.js",
    "content": "﻿/*\n * ------------------------------------------\n * 滚动内存优化控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/profile/profile */\nNEJ.define([\n    'base/element',\n    'base/util',\n    'util/event'\n],function(NEJ,_k,_e,_u,_t,_p,_o,_f,_r){\n    // variable declaration\n    var __cache = {}, // id:node\n        _pro;\n    /**\n     * 滚动内存优化控件，限垂直方向\n     *\n     * @class    module:util/profile/profile._$$ScrollPerf\n     * @param    {Object} arg0   - 可选配置参数\n     * @property {Number} level  - 优化等级，计算位置时位置的缓存控制\n     * [ntb]\n     *   0 | 不做任何优化，每个优化项每次必须重新计算位置【默认】\n     *   1 | 第一次计算位置，后续使用缓存数据\n     * [/ntb]\n     * @property {Number} offset - 当前可视节点的上下偏移个节点可见，如该参数为1则表示当前节点加前后1个节点（共3个节点）可见\n     * @property {String|Node} viewport - 滚动条所在的节点，默认为document.body\n     */\n    /**\n     * 优化触发事件回调函数，输入优化放入内存或放入页面的节点\n     *\n     * @event  module:util/profile/profile._$$ScrollPerf#onoptimize\n     * @param  {Node} arg0 - 被操作的节点\n     */\n    _p._$$ScrollPerf = _k._$klass();\n    _pro = _p._$$ScrollPerf._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method   module:util/profile/profile._$$ScrollPerf#__reset\n     * @param    {Object} arg0   - 可选配置参数\n     * @property {Number} level  - 优化等级，计算位置时位置的缓存控制\n     * |  数值   |  含义                                                 |\n     * | :---    |  :---                                                 |\n     * |   0     |   不做任何优化，每个优化项每次必须重新计算位置【默认】|\n     * |   1     |  第一次计算位置，后续使用缓存数据                     |\n     * @property {Number} offset - 当前可视节点的上下偏移个节点可见，如该参数为1则表示当前节点加前后1个节点（共3个节点）可见\n     * @property {String|Node} viewport - 滚动条所在的节点，默认为document.body\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__level = Math.max(0,\n                       Math.min(1,parseInt(_options.level)||0));\n        this.__number = Math.max(0,parseInt(_options.offset)||0);\n        this.__viewport = e._$get(_options.viewport)||document.body;\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/profile/profile._$$ScrollPerf#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__number;\n        delete this.__viewport;\n        delete this.__scrolltop;\n    };\n    /**\n     * 检测节点是否在可视范围内\n     *\n     * @protected\n     * @method module:util/profile/profile._$$ScrollPerf#__doCheckViewPort\n     * @param  {Node} arg0 -   节点\n     * @return {Number} 节点相对可视区域位置\n     * |  数值   |  含义                |\n     * | :---    |  :---                |\n     * |   -1    |   区域在当前节点之上 |\n     * |   0     |  节点在可视区域中    |\n     * |   1     |  区域在当前节点之下  |\n     */\n    _pro.__doCheckViewPort = function(_element){\n        var _y0 = _element.t,\n            _y1 = _element.b;\n        if (_y0==null||_y1==null){\n            var _offset = e._$offset(_element,this.__viewport),\n            _y0 = _offset.y,\n            _y1 = _y0+_element.offsetHeight;\n            if (this.__level==1){\n                _element.t = _y0;\n                _element.b = _y1;\n            }\n        }\n        if (_y1-this.__scrolltop<0) return 1;\n        if (_y0-this.__scrolltop>this.__viewport.clientHeight) return -1;\n        return 0;\n    };\n    /**\n     * 解析视图范围内的节点\n     *\n     * @protected\n     * @method module:util/profile/profile._$$ScrollPerf#__doParseListInViewPort\n     * @param  {Array}  arg0 - 列表\n     * @param  {Number} arg1 - 偏移\n     * @return {Array}  视图范围内的索引[begin,end]\n     */\n    _pro.__doParseListInViewPort = function(_list,_offset){\n        if (!_list||!_list.length) return;\n        // search first item in viewport\n        var _index = u._$binSearch(_list,\n                     this.__doCheckViewPort._$bind(this));\n        if (_index<0) return;\n        var _beg,_end;\n        _offset = _offset||0;\n        for(var i=1,_node;;i++){\n            _node = _list[_index-i];\n            if (_beg==null&&(!_node||\n                this.__doCheckViewPort(_node)!==0))\n                _beg = _index-i-_offset;\n            _node = _list[_index+i];\n            if (_end==null&&(!_node||\n                this.__doCheckViewPort(_node)!==0))\n                _end = _index+i+_offset;\n            if (_beg!=null&&_end!=null) break;\n        }\n        return [_beg,_end];\n    };\n    /**\n     * 优化图片延时载入\n     *\n     * @protected\n     * @method module:util/profile/profile._$$ScrollPerf#__doPerformImage\n     * @param  {Node} arg0 - 节点\n     * @return {Void}\n     */\n    _pro.__doPerformImage = function(_element){\n        if (!!_element.finished) return;\n        var _ndpf = !1,\n            _list = _element.getElementsByTagName('img');\n        for(var i=0,l=_list.length,_src,_img;i<l;i++){\n            _img = _list[i];\n            _src = e._$dataset(_img,'src');\n            if (!_src) continue;\n            if (!this.__doCheckViewPort(_img)){\n                _ndpf = !0;\n                continue;\n            }\n            e._$dataset(_img,'src','');\n            _img.src = _src;\n        }\n        if (!_ndpf) _element.finished = !0;\n    };\n    /**\n     * 执行优化追加\n     *\n     * @protected\n     * @method module:util/profile/profile._$$ScrollPerf#__doPerformAppend\n     * @param  {Node} arg0 - 节点\n     * @return {Void}\n     */\n    _pro.__doPerformAppend = function(_element){\n        var _node = __cache[_element.id];\n        if (!!_node){\n            _element.insertAdjacentElement('beforeBegin',_node);\n            delete __cache[_element.id];\n            e._$remove(_element,true);\n            _element = _node;\n        }\n        this.__doPerformImage(_element);\n        if (!!_node){\n            _element.memory = false;\n            this._$dispatchEvent('onoptimize',_element);\n        }\n    };\n    /**\n     * 执行优化回收\n     *\n     * @protected\n     * @method module:util/profile/profile._$$ScrollPerf#__doPerformRecycle\n     * @param  {Node} arg0 - 节点\n     * @return {Void}\n     */\n    _pro.__doPerformRecycle = function(_element){\n        var _cache = __cache[_element.id];\n        if (!!_cache) return;\n        var _id = u._$randString(8),\n            _hold = e._$create('div','z-ph js-perf');\n        __cache[_id] = _element;\n        _hold.id = _id;\n        _hold.t  = _element.t;\n        _hold.b  = _element.b;\n        _hold.innerHTML = '&nbsp;';\n        _hold.style.height = _element.offsetHeight+'px';\n        _element.insertAdjacentElement('beforeBegin',_hold);\n        e._$removeByEC(_element);\n        _element.memory = true;\n        this._$dispatchEvent('onoptimize',_element);\n    };\n    /**\n     * 优化图片显示，<img data-src=\"source image src\"\n     *              data-default=\"default image src\"/>\n     *\n     * @method module:util/profile/profile._$$ScrollPerf#_$perfimage\n     * @param  {Number} arg0 - 滚动条距顶部高度\n     * @param  {Array}  arg1 -  待还原图片列表\n     * @return {Array}  设置了原图的图片列表\n     */\n    _pro._$perfimage = function(_offset,_list){\n        this.__scrolltop = _offset||0;\n        // reset image list to default src\n        if (!!_list&&_list.length>0)\n            for(var i=0,l=_list.length,_img,_src;i<l;i++){\n                _img = _list[i];\n                _src = e._$dataset(_img,'default');\n                if (!!_src) _img.src = _src;\n            }\n        var _list = document.getElementsByTagName('img'),\n            _range = this.__doParseListInViewPort(_list);\n        if (!_range) return;\n        // set image list to source src\n        var _result = [];\n        for(var i=_range[0]+1,_img,_src;i<_range[1];i++){\n            _img = _list[i];\n            _src = e._$dataset(_img,'src');\n            if (!!_src&&_src!=_img.src)\n                _img.src = _src;\n            _result.push(_img);\n        }\n        return _result;\n    };\n    /**\n     * 执行滚动优化，<div class=\"js-perf\">content</div>\n     *\n     * @method module:util/profile/profile._$$ScrollPerf#_$performance\n     * @param  {Number} arg0 - 滚动条距顶部高度\n     * @return {Void}\n     */\n    _pro._$performance = function(_offset){\n        this.__scrolltop = _offset||0;\n        var _list = e._$getByClassName(this.__viewport,'js-perf'),\n            _range = this.__doParseListInViewPort(_list,this.__number);\n        if (!_range) return;\n        for(var i=0,l=_list.length,_beg=_range[0],_end=_range[1];i<l;i++)\n            i>_beg&&i<_end ? this.__doPerformAppend(_list[i])\n                           : this.__doPerformRecycle(_list[i]);\n    };\n    /**\n     * 取可视区域内的指定节点列表\n     *\n     * @method module:util/profile/profile._$$ScrollPerf#_$getListInViewPort\n     * @param  {Number} arg0 - 滚动条偏移量\n     * @param  {String} arg1 - 节点标识\n     * @return {Array}  区域内节点列表\n     */\n    _pro._$getListInViewPort = function(_offset,_class){\n        this.__scrolltop = _offset||0;\n        var _list = e._$getByClassName(this.__viewport,_class),\n            _range = this.__doParseListInViewPort(_list,this.__number);\n        return !_range?null:_list.slice(_range[0]+1,_range[1]);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/query/demo/demo.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - NES</title>\n    <meta charset=\"utf-8\" />\n  </head>\n  <body>\n    \n    <div id=\"app\"></div>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            'util/query/query'\n        ],function(query){\n            var page = {\n                init: function(){\n                  query._$one(\"body #app\").innerHTML = \"NEJ is run\";\n                }\n            };\n            \n            page.init();\n        });\n    </script>\n    <script>\n        console.log('xxx');\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/query/nes.js",
    "content": "!function(win, doc, undefined) {\n  // __nes命名空间__\n  var nes = function(node, context){return all(node, context);},\n    locals = {}; //存放local属性...被global坑死了\n\n  // 常用属性local化\n  var ap = Array.prototype,\n    op = Object.prototype,\n    sp = String.prototype,\n    fp = Function.prototype,\n    slice = ap.slice,\n    body = doc.body,\n    testNode = doc.createElement(\"div\"),\n    // 1. Helper(助手函数)\n    // =================================\n    // 将类数组(如Nodelist、Argument)变为数组\n    toArray = function(arr) {\n      return slice.call(arr);\n    },\n    // 够用的短小类型判断\n    typeOf = function(o) {\n      return o == null ? String(o) : op.toString.call(o).slice(8, -1).toLowerCase();\n    },\n    // 够用的简单对象扩展\n    extend = function(o1, o2, override) {\n      for (var i in o2) {\n        if (o1[i] == null || override) o1[i] = o2[i];\n      }\n    },\n    // 最简单先进先出缓存队列, max设置最大缓存长度, 为了不必要重复parse\n    // nes会多次用到这个方法创建cache\n    createCache = function(max) {\n      var keys = [],\n        cache = {};\n      return {\n        set: function(key, value) {\n          if (keys.length > this.length) {\n            delete cache[keys.shift()];\n          }\n          cache[key] = value;\n          keys.push(key);\n          return value;\n        },\n        get: function(key) {\n          if (key === undefined) return cache;\n          return cache[key];\n        },\n        length: max,\n        len: function() {\n          return keys.length;\n        }\n      };\n    },\n    // 让setter型函数fn支持object型的参数\n    // 即支持`set(name:value)`\n    // 也支持`set({name1:value1,name2:value2})`\n    autoSet = function(fn) {\n      return function(key, value) {\n        if (typeOf(key) == \"object\") {\n          for (var i in key) {\n            fn.call(this, i, key[i]);\n          }\n        } else {\n          fn.call(this, key, value);\n        }\n        return this;\n      };\n    },\n    assert = function(fn) {\n      try {\n        return fn();\n      } catch (e) {\n        return false;\n      } finally {\n        testNode = document.createElement(\"div\");\n      }\n    };\n  // Fixed: toArray 低于IE8的 Nodelist无法使用slice获得array\n  try {\n    slice.call(doc.getElementsByTagName(\"body\"));\n  } catch (e) {\n    toArray = function(arr) {\n      var result = [],\n        len = arr.length;\n      for (var i = 0; i < len; i++) {\n        result.push(arr[i]);\n      }\n      return result;\n    };\n  }\n\n  // 扩展ES5 Native支持的函数，坑爹的远古浏览器\n  //es5 trim\n  var trimReg = /^\\s+|\\s+$/g;\n  sp.trim = sp.trim ||\n  function() {\n    return this.replace(trimReg, \"\");\n  };\n\n  //es5 bind\n  fp.bind = fp.bind ||\n  function(context, args) {\n    args = slice.call(arguments, 1);\n    var fn = this;\n    return function() {\n      return fn.apply(context, args.concat(slice.call(arguments)));\n    };\n  };\n  //es5 Array indexOf\n  ap.indexOf = ap.indexOf ||\n  function(a) {\n    for (var i = 0, len = this.length; i < len; i++) {\n      if (a === this[i]) return i;\n    }\n    return -1;\n  };\n\n  // Parser 相关\n  var\n  //抽离出字匹配数目\n  ignoredRef = /\\(\\?\\!|\\(\\?\\:/,\n    extractRefNum = function(regStr) {\n      var left = 0,\n        right = 0,\n        len = regStr.length,\n        ignored = regStr.split(ignoredRef).length - 1; //忽略非捕获匹配\n      for (; len--;) {\n        var letter = regStr.charAt(len);\n        if (len === 0 || regStr.charAt(len - 1) !== \"\\\\\") { //不包括转义括号\n          if (letter === \"(\") left++;\n          if (letter === \")\") right++;\n        }\n      }\n      if (left !== right) throw regStr + \"中的括号不匹配\";\n      else return left - ignored;\n    },\n    //前向引用 如\\1 \\12 等在TRUNK合并时要做处理\n    refIndexReg = /\\\\(\\d+)/g,\n    extractRefIndex = function(regStr, curIndex) {\n      return regStr;\n      // .replace(refIndexReg, function(a, b) {\n      //   return \"\\\\\" + (parseInt(b, 10) + curIndex);\n      // });\n    },\n    // // 生成默认的action，这个会将匹配到的参数推入一个同名的数组内\n    // createAction = function(name) {\n    //   return function(all) {\n    //     var parsed = this.parsed,\n    //       current = parsed[name] || (parsed[name] = [])\n    //       current.push(slice.call(arguments))\n    //   }\n    // },\n    // Object.keys 规则排序时的调用方法\n    keys = Object.keys ||\n  function(obj) {\n    var result = [];\n    for (var prop in obj) {\n      if (obj.hasOwnProperty(prop)) result.push(prop);\n    }\n    return result;\n  },\n  // 将规则中的reg中的macro替换掉\n  cleanRule = function(rule) {\n    var reg = rule.reg;\n    //如果已经是regexp了就转为string\n    if (typeOf(reg) === \"regexp\") reg = reg.toString().slice(1, -1);\n    //将macro替换\n    rule.regexp = reg.replace(replaceReg, function(a, b) {\n      if (b in macros) return macros[b];\n      else throw new Error('can\"t replace undefined macros:' + b);\n    });\n    return rule;\n  }, cleanRules = function(rules) {\n    for (var i in rules) {\n      if (rules.hasOwnProperty(i)) cleanRule(rules[i]);\n    }\n    return rules;\n  };\n\n\n  // ##2. Parser\n  // \n  // 为何要抽象成一个类? 其实这里只用到了一个实例\n  // 事实上这个简单Parser还帮我实现了命令行参数解析，\n  // zen-coding的实现等等, 它可以帮助实现基于正则式的\n  // 字符串解析\n\n\n  function Parser(opts) {\n    opts = opts || {};\n    if (opts.macros) this._macros = opts.macros;\n    this._links = {}; //symbol link map\n    this._rules = {}; //symbol def\n    this.TRUNK = null;\n    this.cache = createCache(opts.maxCache || 200);\n    this.cache.set(\"\", [[] ]); //输入空字符串返回空数组\n  }\n\n  extend(Parser.prototype, {\n    // ### 解析输入字符串input、返回action定义的data数据\n    parse: function(input) {\n      // 清理input数据、因为parsed数据最终会被缓存，\n      // 我们要尽量让相同的选择器只对应一份parsed数据\n      input = clean(input);\n      // 先检查缓存中是否有数据\n      if (parsed = this.cache.get(input)) return parsed;\n      // 如果没有: 初始化参数\n      var parsed = this.parsed = [\n        [null]\n      ];\n      var remain = this.input = input;\n      var TRUNK = this.TRUNK;\n      var prevRemain;\n        // 将remain进行this._process这里每匹配一个字符串都会进行一次reduce\n      while (prevRemain != (remain = remain.replace(TRUNK, this._process.bind(this)))) {\n        prevRemain = remain;\n      }\n      // 如果没有被解析完 证明选择器字符串有不能被解析的部分\n      if (remain !== '') this.error(remain);\n      // 返回数据并推入cache\n      return this.cache.set(input, parsed);\n    },\n    // ###添加新规则 : \n    // 在nes中你可以想象成添加一个与Id、className、pesudo等价简单选择符\n    on: function(rules) {\n      if (typeOf(rules) === \"string\") { //当不是hash传入时\n        var tmp = {};\n        tmp[rules] = arguments[1];\n        rules = tmp;\n      }\n      // 可以同时接受object型或者key, value对的参数\n      for (var i in rules) {\n        var rule = rules[i];\n        if (typeOf(rule) !== \"object\") {\n          rule = {\n            regexp: rule\n          };\n        }\n        var reg = rule.regexp;\n        if (typeOf(reg) === \"regexp\") {\n          rule.regexp = reg.toString().slice(1, -1);\n        }\n        // 初始化order\n        if (rule.order === undefined) rule.order = 1;\n        this._rules[i] = rule;\n      }\n      // 每进行一次新规则监听，都重新组装一次\n      this.setup();\n      return this;\n    },\n    // ###__删除规则__ :\n    // 删除对应规则, 即nes的规则都是在运行时可删可增的\n    off: function(name) {\n      if (typeOf(name) === \"array\") {\n        for (var i = name.length; i--;) {\n          this.off(name[i]);\n        }\n      } else {\n        if (this._rules[name]) {\n          delete this._rules[name];\n        }\n      }\n      return this;\n    },\n    // 获得当前解析位置所在的datum，你只需要在这个datum中塞数据即可\n    current: function() {\n      var data = this.parsed;\n      var piece = data[data.length - 1],\n        len = piece.length;\n      return piece[len - 1] || (piece[len - 1] = {\n        tag: \"*\"\n      });\n    },\n    error: function(info) {\n      throw Error(\"输入  \" + this.input + \"  含有未识别语句:\" + info || \"\");\n    },\n\n    clone: function(parser) {\n      return new Parser().on(this._rules);\n    },\n    // __`this.parser`__的依赖方法，\n    // 即遍历links检查是否有子匹配满足关系，\n    // 有则推入对应的action数组,\n    // 注意由于其是是replace方法的调用，每次都要返回\"\"完成\n    // reduce操作\n    _process: function() {\n      var links = this._links,\n        rules = this._rules,\n        args = slice.call(arguments);\n\n        for (var i in links) {\n          var link = links[i],\n            retain = link[1],\n            index = parseInt(link[0]);\n            if (args[index] && (rule = rules[i])) {\n              rule.action.apply(this, args.slice(index, index + retain));\n              return \"\";\n            }\n        }\n      return \"\";\n    },\n    // 组装\n    setup: function() {\n      cleanRules(this._rules);\n      var curIndex = 1,\n        //当前下标\n        splits = [],\n        rules = this._rules,\n        links = this._links,\n        ruleNames = keys(rules).sort(function(a, b) {\n          return rules[a].order >= rules[b].order;\n        }),\n        len = ruleNames.length;\n\n      for (; len--;) {\n        var i = ruleNames[len],\n          rule = rules[i],\n          retain = extractRefNum(rule.regexp) + 1; // 1就是那个all\n        if (rule.filter && !filters[i]) {\n          filters[i] = rule.filter;\n        } //将filter转移到filters下\n        links[i] = [curIndex, retain]; //分别是rule名，参数数量\n        var regexp = extractRefIndex(rule.regexp, curIndex - 1);\n        curIndex += retain;\n        splits.push(regexp);\n      }\n      this.TRUNK = new RegExp(\"^(?:(\" + splits.join(\")|(\") + \"))\");\n      return this;\n    }\n  });\n\n\n\n  // ### parse的规则定义部分开始\n  // 一些用到的正则式，但是又不属于parser的规则组成\n  var\n  replaceReg = /\\{\\{([^\\}]*)\\}\\}/g,\n    //替换rule中的macro\n    nthValueReg = /^(?:(\\d+)|([+-]?\\d*)?n([+-]\\d+)?)$/,\n    // nth伪类的value规则\n    posPesudoReg = /^(nth)[\\w-]*(-of-type|-child)/,\n    //判断需要pos\n    // 第一个cache 用来装载nth伪类中的参数解析后的数据\n    // 如nth-child、nth-of-type等8个伪类\n    nthCache = createCache(100),\n    // 提取nthValue中的有用信息 比如an + b 我们需要提取出a以及,b并对额外情况如缺少a参数或b参数\n    // 或者有a、b小于0这些情况作统一处理，返回find适合使用的数据\n    extractNthValue = function(param) {\n      var step, start, res;\n      //如果无参数 当成是获取第一个元素\n      if (!param || !(param = param.replace(/\\s+/g, \"\"))) {\n        return {\n          start: 1,\n          step: 0\n        };\n      }\n      if (res = nthCache.get(param)) return res;\n      // 对even odd等转化为标准的a，b组合(即step与start)\n      if (param == \"even\") {\n        start = 2;\n        step = 2;\n      } else if (param == \"odd\") {\n        step = 2;\n        start = 1;\n      } else {\n        res = param.match(nthValueReg);\n        // 对错误的nth参数抛出错误\n        if (!res) step = null; // 无论其他参数，如果step为null，则永远为false\n        else {\n          if (res[1]) {\n            step = 0;\n            start = parseInt(res[1]);\n          } else {\n            if (res[2] == \"-\") res[2] = \"-1\";\n            step = res[2] ? parseInt(res[2]) : 1;\n            start = res[3] ? parseInt(res[3]) : 0;\n          }\n        }\n      }\n      if (start < 1) {\n        if (step < 1) {\n          step = null; //标志false\n        } else {\n          start = -(-start) % step + step;\n        }\n      }\n      return nthCache.set(param, {\n        start: start,\n        step: step\n      });\n    };\n\n    // ### parse Rule 相关\n    // 了解bison等解析器生成的同学可以把这部分看成是词法与语法定义的杂糅\n    // 很混乱也很不标准，但对于选择器这种最简单的DSL其实够用，并且有了奇效\n    // 整个Parser根据rules动态产生(即可在使用时发生改变)\n    // 具体的流程是下面的rules对象定义了一组语法(词法?)rule——如attribute，\n    // 你可以把每个rule中的reg想象成一个token(word?),这些token可能会有{{word}}这种占位符\n    // 占位符首先会被macros中对应的macro替换，然后这些token会被组装成一个大版的Regexp，即上面的\n    // Trunk变量,这个过程没什么特殊，一般比较优秀的选择器都是基于这个方法。 在nes中,最终的Trunk可能是\n    // 这样的:\n    //\n    // `/(\\s*,\\s*)|(#([\\w\\u4e00-\\u9fbf-]+))|(\\*|\\w+)|(\\.([\\w\\u4e00-\\u9fbf-]+))|\n    // (:([\\w\\u4e00-\\u9fbf-]+)(?:\\(([^\\(\\)]*|(?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\))?)|\n    // (\\[([\\w\\u4e00-\\u9fbf-]+)(?:([*^$|~!]?=)['\"]?((?:[\\w\\u4e00-\\u9fbf-]||\\s)+)['\"]?)?\\])|(::([\\w\\u4e00-\\u9fbf-]+))\n    // |([>\\s+~&%](?!=))|(\\s*\\{\\s*(\\d*),(\\-?\\d*)\\s*\\}\\s*)/g`\n    // \n    // 看到上面那长串，你大概理解了将regexp按词法分开这样做的第一个原因 : __维护__. \n    // 第二个原因就是: __效率__  一次大型正则的调用时间要远低于多次小型正则的匹配(前提它们做同样规模的匹配)\n  var\n  // 一些macro\n  macros = {\n    split: \"\\\\s*,\\\\s*\",\n    // 分隔符\n    operator: \"[*^$|~!]?=\",\n    // 属性操作符 如= 、!=\n    combo: \"[>\\\\s+~](?!=)\",\n    // 连接符 如 > ~ \n    word: \"[\\\\\\\\\\\\w\\\\u00A1-\\\\uFFFF-]\"\n  },\n    // 语法规则定义\n    rules = {\n      split: {\n        // 分隔符 如 ，\n        reg: \"{{split}}\",\n        action: function(all) {\n          this.parsed.push([null]);\n        },\n        order: 0\n      },\n      // id 如 #home\n      id: {\n        reg: \"#({{word}}+)\",\n        action: function(all, id) {\n          this.current().id = id;\n        }\n      },\n      // 节点类型选择符 如 div\n      tag: {\n        reg: \"\\\\*|[a-zA-Z-]\\\\w*\",\n        // 单纯的添加到\n        action: function(tag) {\n          this.current().tag = tag.toLowerCase();\n        }\n      },\n      // 类选择符 如 .m-home\n      classList: {\n        reg: \"\\\\.({{word}}+)\",\n        action: function(all, className) {\n          var current = this.current(),\n            classList = current.classList || (current.classList = []);\n            classList.push(className);\n        }\n      },\n      // 伪类选择符 如 :nth-child(3n+4)\n      pesudos: {\n        reg: \":({{word}}+)\" + //伪类名\n        \"(?:\\\\(\" + //括号开始\n        \"([^\\\\(\\\\)]*\" + //第一种无括号\n        \"|(?:\" + //有括号(即伪类中仍有伪类并且是带括号的)\n        \"\\\\([^\\\\)]+\\\\)\" + //括号部分\n        \"|[^\\\\(\\\\)]*\" + \")+)\" + //关闭有括号\n        \"\\\\))?\",\n        // 关闭最外圈括号\n        action: function(all, name, param) {\n          var current = this.current(),\n            pesudos = current.pesudos || (current.pesudos = []),\n            name = name.toLowerCase(),\n            res = {\n              name: name\n            };\n\n          if (param) param = param.trim();\n          if (posPesudoReg.test(name)) {\n            // parse 的成本是很小的 尽量在find前把信息准备好\n            // 这里我们会把nth-child(an+b) 的 a 与 b 在不同输入下标准化\n            param = extractNthValue(param);\n          }\n          if (param) res.param = param;\n          pesudos.push(res);\n        }\n      },\n      // 属性选择符  如  [class=hahaha]\n      //\n      // 这里以属性选择符为例，说明下reg与action的关系\n      // \n      attributes: {\n        reg: \"\\\\[\\\\s*({{word}}+)(?:({{operator}})[\\'\\\"]?([^\\'\\\"\\\\[]+)[\\'\\\"]?)?\\\\s*\\\\]\",\n        action: function(all, key, operator, value) {\n          var current = this.current(),\n            attributes = current.attributes || (current.attributes = []);\n            var res = {};\n          attributes.push({\n            key: key,\n            operator: operator,\n            value: value\n          });\n        }\n      },\n      // 伪元素可以实现么？ 占位\n      combo: {\n        reg: \"\\\\s*({{combo}})\\\\s*\",\n        action: function(all, combo) {\n          var data = this.parsed,\n            cur = data[data.length - 1];\n            this.current().combo = combo;\n            cur.push(null);\n        },\n        order: 0\n      }\n    };\n\n  var cleanReg = new RegExp(\"\\\\s*(,|\" + macros.combo + \"|\" + macros.operator + \")\\\\s*\", \"g\");\n  clean = function(sl) {\n      return sl.trim().replace(/\\s+/g, \" \").replace(cleanReg, \"$1\");\n    };\n    // ### parser生成\n    // 初始化parser实例\n  var parser = new Parser();\n  parser.on(rules); //生成规则\n  // 为了兼容前面版本，仍然提供这个parse函数, 也为了与find想对应\n\n\n  function parse(sl) {\n    return parser.parse(sl);\n  }\n\n  //   3. Finder\n  // ================\n  //   Util\n  // -------------------------\n  // 将nodelist转变为array\n  //  DOM related Util\n  // --------------------\n  var root = doc.documentElement || doc;\n  var attrMap = {\n    'for': \"htmlFor\",\n    \"href\": function(node) {\n      return \"href\" in node ? node.getAttribute(\"href\", 2) : node.getAttribute(\"href\");\n    },\n    \"type\": function(node) {\n      return \"type\" in node ? node.getAttribute(\"type\") : node.type;\n    }\n  };\n  var checkTagName = assert(function() {\n    testNode.appendChild(doc.createComment(\"\"));\n    // 有些版本的getElementsByTagName(\"*\")会返回注释节点\n    return !testNode.getElementsByTagName(\"*\").length ||\n    // 低版本ie下input name 或者 id为length时 length返回异常\n    typeof doc.getElementsByTagName(\"input\").length !== \"number\";\n  });\n  //form __sizzle__line200 判断getAttribute是否可信\n  var checkAttributes = assert(function() {\n    testNode.innerHTML = \"<select></select>\";\n    var type = typeOf(testNode.lastChild.getAttribute(\"multiple\"));\n    // IE8 returns a string for some attributes even when not present\n    return type !== \"boolean\" && type !== \"string\";\n  });\n  // 将nth类方法的判断部分统一抽离出来,\n  // 其中type代表是否是nth-type-of类型的判断,下面类似\n\n\n  function checkNth(node, type) {\n    return type? node.nodeName === type : node.nodeType === 1;\n  }\n  // 获得父节点node的顺数第n(从1开始)个子节点\n\n\n  function nthChild(node, type) {\n    var node = node.firstChild;\n    return (!node || checkNth(node, type)) ? node : nthNext(node, type);\n  };\n  // 获得父节点node的倒数第n(从1开始)个子节点\n\n\n  function nthLastChild(node,type) {\n    var node = node.lastChild;\n    return (!node || checkNth(node, type))? node:nthPrev(node, type);\n  };\n  // 获得节点node的第n(从1开始)个前置兄弟节点\n\n\n  function nthPrev(node, type) {\n    while (node = node.previousSibling) {\n      if (checkNth(node, type)) return node;\n    }\n    return node;\n  };\n  // 获得节点node的倒数第n(从1开始)个前置兄弟节点\n\n\n  function nthNext(node, type) {\n    while (node = node.nextSibling) {\n      if (checkNth(node, type)) return node;\n    }\n    return node;\n  };\n  // 获得节点node的key属性的值, 修改自from sizzle...蛋疼啊各浏览器的属性获取\n\n  function getAttribute(node, key) {\n    var map = attrMap[key];\n    if (map) return typeof map === \"function\" ? map(node) : node[map];\n    if (checkAttributes) {\n      return node.getAttribute(key);\n    }\n    var attrNode = node.getAttributeNode(key);\n    // 对于selected checked 当返回为bool值时  将其标准化为 selected = \"selected\"\n    // 方便后续处理\n    // 很多时候null可以作为标志位，nes中大部分特殊flag都用null标示\n    return typeof node[key] === \"boolean\" \n            ? node[key] ? key : null\n            : (attrNode && attrNode.specified ?attrNode.value : null);\n  };\n  // __数组去重__\n\n\n  function distinct(array) {\n    for (var i = array.length; i--;) {\n      var n = array[i];\n      // 先排除 即 如果它是清白的 后面就没有等值元素\n      array.splice(i, 1, null);\n      if (~array.indexOf(n)) {\n        array.splice(i, 1); //不清白\n      } else {\n        array.splice(i, 1, n); //不清白\n      }\n    }\n    return array;\n  }\n  // 从sizzle抄袭的 document sorter \n  // 将匹配元素集按文档顺序排列好 这很重要!\n  var sortor = (doc.compareDocumentPosition) ?\n  function(a, b) {\n    if (!a.compareDocumentPosition || !b.compareDocumentPosition) return 0;\n    return a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;\n  } : ('sourceIndex' in doc) ?\n  function(a, b) {\n    if (!a.sourceIndex || !b.sourceIndex) return 0;\n    return a.sourceIndex - b.sourceIndex;\n  } : function(a, b) {\n    var i = 0,\n      ap = [a],\n      bp = [b],\n      aup = a.parentNode,\n      bup = b.parentNode,\n      cur = aup;\n\n    if (a === doc) {\n      return -1;\n    } else if (b === doc) {\n      return 1;\n    } else if (!aup && !bup) {\n      return 0;\n    } else if (!bup) {\n      return -1;\n    } else if (!aup) {\n      return 1;\n    } else if (aup === bup) {\n      return siblingCheck(a, b);\n    }\n    while (cur) {\n      ap.unshift(cur);\n      cur = cur.parentNode;\n    }\n    cur = bup;\n    while (cur) {\n      bp.unshift(cur);\n      cur = cur.parentNode;\n    }\n    while (ap[i] === bp[i]) {\n      i++;\n    }\n    return siblingCheck(ap[i], bp[i]);\n  };\n\n  function siblingCheck(a, b) {\n    if (a && b) {\n      var cur = a.nextSibling;\n      while (cur) {\n        if (cur === b) {\n          return -1;\n        }\n        cur = cur.nextSibling;\n      }\n    }\n    return a ? 1 : -1;\n  };\n\n  function uniqueSort(nodeList) {\n    return distinct(nodeList.sort(sortor));\n  };\n\n  // ### nth position Cache 部分\n  // 对于nth类型的查找，有时候一次节点查找会遍历到多次相同节点，\n  // 由于一次节点查找时，由于js的单线程，节点不可能发生改变，介于此，我们将\n  // nth类的node的节点位置缓存起来，在本次查找结束后再清空\n  // 获得node的唯一标示\n  var getUid = (function(token) {\n    var _uid = 0;\n    return function(node) {\n      return node._uid || (node._uid = token + _uid++);\n    };\n  })(\"nes_\" + (+new Date).toString(36));\n  // 创建nth相关的Filter，由于都类似，就统一通过工厂函数生成了\n  // 参数有两个  \n  //    1. isNext: 代表遍历顺序是向前还是向后\n  //    2. isType: 代表是否是要指定nodeName\n\n\n  function createNthFilter(isNext, isType) {\n    var next, prev, cacheKey, getStart;\n    if (isNext) {\n      cacheKey = isType ? \"type\" : \"child\";\n      // if(typeof isType === \"function\") cacheKey = \"match\"\n      next = nthNext;\n      prev = nthPrev;\n      getStart = nthChild;\n    } else {\n      // Fixed:!!! 这里cache是首次生成的cache被写死了，即使后面clear了也没有用,\n      // 即永远无法被释放\n      cacheKey = \"last\" + (isType ? \"type\" : \"child\");\n      // if(typeof isType === \"function\") cacheKey = \"last-match\"\n      prev = nthNext;\n      next = nthPrev;\n      getStart = nthLastChild;\n    }\n    // 实际返回函数, param即pesudo的action定义的参数形如\n    // `{step:1, start:1}` 所有的类似even、odd或者其他形如n、-3n-11都会标准化\n    // 成这种形势\n    return function(node, param) {\n      var cache = nthPositionCache[cacheKey];\n      if (node === root) return false; // 如果是html直接返回false 坑爹啊\n      var _uid = getUid(node),\n        parent = node.parentNode,\n        traverse = param.step > 0 ? next : prev,\n        step = param.step,\n        start = param.start,\n        type = isType && node.nodeName;\n        //Fixed\n      if (step === null) return false; //means always false\n      if (!cache[_uid]) {\n        var startNode = getStart(parent, type),\n          index = 0;\n          do {\n            cache[getUid(startNode)] = ++index;\n            nthPositionCache.length++;\n          } while (startNode = next(startNode, type));\n      }\n      var position = cache[_uid];\n      if (step === 0) return position === start;\n      return ((position - start) / step >= 0) && ((position - start) % step === 0);\n    };\n  }\n  // \n  var nthPositionCache = {length: 1 };\n  function clearNthPositionCache() {\n    if (nthPositionCache.length) {\n      nthPositionCache = {\n        child: {},\n        lastchild: {},\n        type: {},\n        lasttype: {},\n        length: 0\n      };\n    }\n  }\n  // 初始化positioncache\n  clearNthPositionCache();\n\n\n  // 这里的几个finders是第一轮获取目标节点集的依赖方法\n  // 我没有对byClassName做细致优化，比如用XPath的方式\n  // form sizzle line 147\n  var finders = {\n    byId: function(id) {\n      var node = doc.getElementById(id);\n      return node ? [node] : [];\n    },\n    byClassName: doc.getElementsByClassName ? function(classList, node) {\n      classList = classList.join(\" \");\n      return toArray((node || doc).getElementsByClassName(classList));\n    } : null,\n    byTagName: checkTagName ? function(tagName, node) {\n      var results = (node || doc).getElementsByTagName(tagName);\n      return toArray(results);\n    } : function(tagName, node) {\n      var results = (node || doc).getElementsByTagName(tagName);\n      var elem, tmp = [],\n        i = 0;\n      for (;\n      (elem = results[i]); i++) {\n        if (elem.nodeType === 1) tmp.push(elem);\n      }\n      return tmp;\n    }\n  };\n  // ### filter: \n  // Action中塞入的数据会统一先这里处理，可能是直接处理如id、class等简单的.\n  // 也可能是分发处理，甚至是多重的分发，如那些复杂的attribute或者是pesudo\n  // 这里简化到过滤单个节点 逻辑清晰 ,但可能性能会降低，因为有些属性会重复获取\n  var filters = {\n    id: function(node, id) {\n      return node.id === id;\n    },\n    classList: function(node, classList) {\n      var len = classList.length,\n        className = \" \" + node.className + \" \";\n      for (; len--;) {\n        if (className.indexOf(\" \" + classList[len] + \" \") === -1) {\n          return false;\n        }\n      }\n      return true;\n    },\n    tag: function(node, tag) {\n      if (tag == \"*\") return true;\n      return node.tagName.toLowerCase() === tag;\n    },\n    // pesudos会分发到ExpandsFilter中pesudo中去处理\n    pesudos: function(node, pesudos) {\n      var len = pesudos.length,\n        pesudoFilters = expandFilters[\"pesudos\"];\n\n      for (; len--;) {\n        var pesudo = pesudos[len],\n          name = pesudo.name,\n          filter = pesudoFilters[name];\n\n        if (!filter) throw Error(\"不支持的伪类:\" + name);\n        if (!filter(node, pesudo.param)) return false;\n      }\n      return true;\n    },\n    // attributes会分发到ExpandsFilter中的operator去处理\n    attributes: function(node, attributes) {\n      var len = attributes.length,\n        operatorFilters = expandFilters[\"operators\"];\n\n      for (; len--;) {\n        var attribute = attributes[len],\n          operator = attribute[\"operator\"],\n          filter = operatorFilters[operator],\n          nodeValue = getAttribute(node, attribute.key);\n\n          if (nodeValue === null) {\n            if (operator !== \"!=\") return false;\n            continue;\n          }\n        if (!operator) continue;\n        if (!filter) throw Error(\"不支持的操作符:\" + operator);\n        if (!filter(attribute.value, nodeValue + \"\")) return false;\n      }\n      return true;\n    }\n  };\n\n  // expandFilters \n  // -------------------------\n  // 原生可扩展的方法\n  var expandFilters = {\n    // __扩展连接符__:\n    // 选择符filter 与其他filter不同 node 同样是当前节点 区别是\n    // 如果成功返回成功的上游节点(可能是父节点 可能是兄弟节点等等)\n    // 其中 match(node) 返回 这个上游节点是否匹配剩余选择符(内部仍是一个递归)\n    combos: {\n      \">\": function(node, match) {\n        var parent = node.parentNode;\n        if (match(parent)) return parent;\n      },\n      \"~\": function(node, match) {\n        var prev = nthPrev(node);\n        while (prev) {\n          if (match(prev)) return prev;\n          prev = nthPrev(prev);\n        }\n      },\n      \" \": function(node, match) {\n        var parent = node.parentNode;\n        while (parent) {\n          var pass = match(parent);\n          if (pass) return parent;\n          if (pass === null) return null;\n          parent = parent.parentNode;\n        }\n        return null;\n      },\n      \"+\": function(node, match) {\n        var prev = nthPrev(node);\n        if (prev && match(prev)) return prev;\n      }\n    },\n    // __扩展操作符__ :\n    operators: {\n      \"^=\": function(value, nodeValue) {\n        if (nodeValue == null) return false;\n        return nodeValue.indexOf(value) === 0;\n      },\n      \"=\": function(value, nodeValue) {\n        return nodeValue === value;\n      },\n      \"~=\": function(value, nodeValue) {\n        if (nodeValue == null) return false;\n        return ~ (\" \" + nodeValue + \" \").indexOf(value);\n      },\n      \"$=\": function(value, nodeValue) { //以value结尾\n        return nodeValue.substr(nodeValue.length - value.length) === value;\n      },\n      \"|=\": function(value, nodeValue) { // 连接符\n        return ~ (\"-\" + nodeValue + \"-\").indexOf(\"-\" + value + \"-\");\n      },\n      \"*=\": function(value, nodeValue) { //出现在nodeValue的任意位置\n        return ~ (nodeValue).indexOf(value);\n      },\n      \"!=\": function(value, nodeValue) {\n        return nodeValue !== value;\n      }\n    },\n    // __扩展伪类__:\n    pesudos: {\n      //TODO:这里如果出自 SELECtorAPI 标注下处处\n      \"not\": function(node, sl) {\n        return !matches(node, sl);\n      },\n      \"matches\": function(node, sl) {\n        return matches(node, sl);\n      },\n      // child pesudo 统一由工厂函数生成\n      \"nth-child\": createNthFilter(true, false),\n      \"nth-last-child\": createNthFilter(false, false),\n      \"nth-of-type\": createNthFilter(true, true),\n      \"nth-last-of-type\": createNthFilter(false, true),\n  \n      \"first-child\": function(node) {\n        return !nthPrev(node);\n      },\n      \"last-child\": function(node) {\n        return !nthNext(node);\n      },\n      \"last-of-type\": function(node) {\n        return !nthNext(node, node.nodeName);\n      },\n      \"first-of-type\": function(node) {\n        return !nthPrev(node, node.nodeName);\n      },\n      \"only-child\": function(node) {\n        return !nthPrev(node) && !nthNext(node);\n      },\n      \"only-of-type\": function(node) {\n        return !nthPrev(node, node.nodeName) && !nthNext(node, node.nodeName);\n      },\n      //找出有具体text内容的节点\n      \"contains\": function(node, param) {\n        return ~ (node.innerText || node.textContent || '').indexOf(param);\n      },\n      \"checked\": function(node) {\n        return !!node.checked || !! node.selected;\n      },\n      \"selected\": function(node) {\n        return node.selected;\n      },\n      \"enabled\": function(node) {\n        return node.disabled === false;\n      },\n      \"disabled\": function(node) {\n        return node.disabled === true;\n      },\n      \"empty\": function(node) {\n        var nodeType;\n        node = node.firstChild;\n        while (node) {\n          if (node.nodeName > \"@\" || (nodeType = node.nodeType) === 3 || nodeType === 4) {\n            return false;\n          }\n          node = node.nextSibling;\n        }\n        return true;\n      },\n      \"focus\": function(node) {\n        return node === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !! (node.type || node.href || ~node.tabIndex);\n      },\n      \"target\": function(node, param) {\n        var id = node.id || node.name;\n        if (!id) return false;\n        return (\"#\" + id) === location.hash;\n      }\n    }\n  };\n\n  // 这里主要是整合之前的ExpandsFilter中的mathch, 单层数据\n\n\n  function matchDatum(node, datum, ignored) {\n    var subFilter;\n    for (var i in datum) {\n      if (ignored !== i && (subFilter = filters[i]) && !subFilter(node, datum[i])) {\n        return false;\n      }\n    }\n    return true;\n  };\n  // 这个全局cache的引入是为了避免多次传入参数。\n  // 当然全局的缺点也很明显，维护会不方便, 不利于测试\n  var matchesCache = null; //保存那些matches函数\n  \n\n  function matchData(node, data, ignored) { // 稍后再看存入step\n    var len = data.length,\n      datum = data[len - 1];\n      // 首先要满足自身\n    if (!matchDatum(node, datum, ignored)) return false;\n    else {\n      if (len == 1) return true;\n      var nextDatum = data[len - 2],\n        getNext = expandFilters.combos[nextDatum.combo],\n        match = matchesCache[len - 2],\n        next = getNext(node, match);\n\n        if (next) return true;\n        else return false;\n    }\n  };\n  //动态产生供FilterOneNode使用的match\n\n\n  function createMatch(data) {\n    return function(node) {\n      if (node == root || node == null || node == doc) return null; //null 相当于休止符\n      return matchData(node, data);\n    };\n  };\n\n  function createMatches(data) {\n    var matches = [];\n    for (var i = 0, len = data.length; i < len; i++) {\n      matches.push(createMatch(data.slice(0, i + 1)));\n    }\n    return matches;\n  };\n  // 过滤主函数filter\n  // -----------------------------------\n  // 自底向上过滤非匹配节点\n\n\n  function filter(results, data, ignored) {\n    if (!data.length) return results;\n    //这里是为了缓存match匹配函数\n    var preMatchesCache = matchesCache;\n    matchesCache = createMatches(data);\n    for (var i = results.length; i--;) {\n      if (!matchData(results[i], data, ignored)) {\n        results.splice(i, 1);\n      }\n    }\n    // Fixed: 因为一次filter可能会有字filter调用，比如matches、not、include\n    matchesCache = preMatchesCache; // warning :以后写全局变量一定当心\n    return results;\n  }\n  // 获得第一次目标节点集\n\n\n  function getTargets(data, context) {\n    var results, ignored, lastPiece = data[data.length - 1];\n    if (lastPiece.id) {\n      results = finders.byId(lastPiece.id);\n      ignored = \"id\";\n    } else if (lastPiece.classList && lastPiece.classList.length && finders.byClassName) {\n      results = finders.byClassName(lastPiece.classList, context);\n      ignored = \"classList\";\n    } else {\n      results = finders.byTagName(lastPiece.tag || \"*\", context);\n      ignored = \"tag\";\n    }\n    if (!results.length) return results;\n    return filter(results, data, ignored);\n  }\n  // API : find (private)\n  // -------------\n  // 根据parse后的数据进行节点查找\n  // options:\n  //    1. parsed.data  parse数据为一数组\n  //    2. node         context节点\n  // 事实上没有data这个单词，我这里算是自定了这个单词\n  //     datas : [data,data]   \n  //     data : [datum, datum]\n  //     datum: {tag:\"*\"....etc}\n\n\n  function find(datas, context) {\n    if (!datas[0][0]) return [];\n    var results = [],\n      notNullResult = 0;\n\n    for (var i = 0, len = datas.length; i < len; i++) {\n      var data = datas[i],\n        dlen = data.length,\n        last = data[dlen - 1],\n        result = getTargets(data, context);\n\n      if (result && result.length) {notNullResult++;};\n      if (!results) results = result;\n      else results =results.concat(result);\n    }\n    clearNthPositionCache();//清理\n    if (notNullResult > 1) uniqueSort(results);\n    return results;\n  }\n  // API : 测试用get相当于all (private)\n  // -------------------------------------\n  // 为了测试时避免原生querySelector的影响\n  // \n\n\n  function get(sl, context) {\n    var data = parse(sl);\n    var result = find(data, context || doc);\n    return result;\n  }\n\n  // API \n  // ----------------------------------------------------------------------\n  var supportQuerySelector = !! doc.querySelector;\n\n  // API1——__one__:对应标准的querySelector方法\n\n\n  function one(sl, context) {\n    var node;\n    if (supportQuerySelector && !nes.debug) {\n      try {\n        node = (context || doc).querySelector(sl);\n      } catch (e) {\n        node = get(sl, context)[0];\n      }\n    } else {\n      node = get(sl, context)[0];\n    }\n    return node;\n  }\n\n  // API2——__all__\n  // -------------------------------\n  // 对应标准的querySelectorAll方法\n\n\n  function all(sl, context) {\n    var nodeList;\n    if (supportQuerySelector && !nes.debug) {\n      try {\n        nodeList = toArray((context || doc).querySelectorAll(sl));\n      } catch (e) {\n        nodeList = get(sl, context);\n      }\n    } else {\n      nodeList = get(sl, context);\n    }\n    return nodeList;\n  }\n\n  // API 3: \n  // ----------------------------------------------------------------------\n  // 对应标准的matches方法\n  // nes的matches功能稍强，它支持用分隔符链接符组合的复杂选择器\n  // 即与all、one函数的支持是一样的\n  //\n  // 注: 由于:not与:matches依赖于这个函数 ,所以同样支持复杂选择器\n\n\n  function matches(node, sl) {\n    if (!node || node.nodeType !== 1) return false;\n    var datas = parse(sl),\n      len = datas.length;\n    if (!datas[len - 1][0]) return false;\n    for (; len--;) {\n      if (matchOneData(node, datas[len])) return true;\n    }\n    return false;\n  }\n\n  // matches 单步调用方法\n\n\n  function matchOneData(node, data) {\n    var len = data.length;\n    if (!matchDatum(node, data[len - 1])) {\n      return false;\n    } else {\n      return filter([node], data.slice(0)).length === 1;\n    }\n  }\n\n  // ASSEMBLE \n  // =========================\n  // 组装分为几个步骤\n  //\n  // 1. 生成pesudo 、 operator、combo 等expand方法\n  // ----------------------------------------------------------------------\n  // 具体扩展方法的使用请参见 [nes的github](https://github.com/leeluolee/nes)\n  // 统一由工厂函数createExpand\n  ;\n  (function createExpand(host, beforeAssign) {\n    for (var i in host) {\n      nes[i] = (function(i) {\n        var container = host[i];\n        // autoSet代表了这三个函数除了key、value参数\n        // 也支持字面量的参数输入\n        return autoSet(function(key, value) {\n          // Warning: 直接覆盖，如果存在的话\n          container[key] = value;\n          if (i in beforeAssign) {\n            beforeAssign[i](key, value);\n          }\n        });\n      })(i);\n    }\n    // 有些扩展如combos、operators由于为了避免冲突\n    // 关键字都写入了正则式中，这种情况下需要将新的正则式\n    // 填入相关正则，并进行parser的setup\n  })(expandFilters, {\n    \"operators\": function(key) {\n      var befores = macros.operator.split(\"]\");\n      befores.splice(1, 0, key.charAt(0) + \"]\");\n      macros.operator = befores.join(\"\");\n      parser.setup();\n    },\n    \"combos\": function(key) {\n      var befores = macros.combo.split(\"]\");\n      befores.splice(1, 0, key + \"]\");\n      macros.combo = befores.join(\"\");\n      parser.setup();\n    }\n  });\n\n  // 2. 暴露API\n  // -------------------------------------\n  //\n  // 直接设置其为true 来强制不适用原生querySelector Api\n  nes.debug = false; \n  nes._nthCache = nthCache;\n  // parser , 抽离的parser部分\n  // ---------------------------\n  // 它可以:\n  //\n  //    1. parser.parse 解析内部规则定义的字符串匹配\n  //    2. parser.on    添加新规则\n  //    3. parser.clone 复制此parser，这个作用会在后面的zen-coding的demo中体现\n  //    4. parser.off   删除规则\n  //    5. parser.cache 缓存控制\n  nes.parser = parser;\n\n  //解析, 这个将被移除，使用parser.parse来代替\n  nes.parse = parse;\n  //查找parser解析后的data代表的节点 __private__\n  nes._find = find;\n  //测试时排除原生querySelector的影响 __deprecated__! 使用nes.debug来控制\n  nes._get = get;\n  //        *主要API*\n  // -------------------------\n  nes.one = one; \n  nes.all = all; \n  nes.matches = matches;\n  // 内建扩展 api 这三个已经内建:\n  // \n  // 1. `pesudos`\n  // 2. `operators`\n  // 3. `combos`\n  nes._uniqueSort = uniqueSort;\n  nes._cleanSelector = clean;\n  nes._getUid = getUid;\n\n\n  //          5.Exports\n  // ----------------------------------------------------------------------\n  // 暴露API:  amd || commonjs  || global \n  // 支持commonjs\n  if (typeof exports === 'object') {\n    module.exports = nes;\n    // 支持amd\n  } else if (typeof define === 'function' && define.amd) {\n/* */define(function() {\n      return nes;\n    });\n  } else {\n    // 直接暴露到全局\n    win.nes = nes;\n  }\n\n  //        6. extension\n  //-------------------------------------------------------------\n  // 很多人不看extend文件夹， 所以这部分也作为Demo实例\n\n  /**\n   * nth Math 的调用方法\n   * @param  {[type]} first [description]\n   * @return {[type]}\n   */\n  function nthMatch(first) {\n    return function(node, param) {\n      var tmp = param.split(/\\s+of\\s+/);\n      if(tmp.length<2) throw Error(\"no 'of' keyword in nth-match\\\"s selector\");\n\n      var params = extractNthValue(tmp[0]),\n        sl = tmp[1],\n        testNode = node.parentNode[first? \"firstChild\":\"lastChild\"],\n        next = first? \"nextSibling\" : \"previousSibling\",\n        step = params.step,\n        start = params.start,\n        position = 0;\n\n        if(!matches(node, sl)) return false;\n        if (step === null) return false; //means always false\n        do {\n          if (testNode.nodeType === 1 && nes.matches(testNode, sl)) position++;\n          if (testNode === node) break;\n        } while (testNode = testNode[next]);\n        \n        if (step === 0) return position === start;\n        return ((position - start) / step >= 0) && ((position - start) % step === 0);\n    };\n  }\n  nes.pesudos({\n    // 例如 :nth-match(3 of li.active) 第三个满足这个li.active的节点\n    \"nth-match\": nthMatch(true),\n    \"nth-last-match\": nthMatch(false),\n    \"local-link\": function(_node, param){\n      if(param) param = parseInt(param);\n    }\n  });\n}(window, document, undefined);"
  },
  {
    "path": "src/util/query/query.js",
    "content": "/*\n * NES css selector engine\n * Copyright (C) 1997-2012 NetEase, Inc.\n *\n * NES is released under the MIT license\n\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n/*\n * ------------------------------------------\n * CSS选择器API封装实现文件\n * CSS选择器API实现基于NES开源库，此处仅做NEJ规范适配\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/query/query */\nNEJ.define([\n    'base/global',\n    './nes.js'\n],function(NEJ,_t0,_p,_o,_f,_r){\n    /**\n     * 节点选择器\n     *\n     * 结构示例\n     * ```html\n     * <ul class=\"w-tab\">\n     *   <li class=\"itm\">Tab-0</li>\n     *   <li class=\"itm\">Tab-1</li>\n     *   <li class=\"itm\">Tab-2</li>\n     *   <li class=\"itm js-selected\">Tab-3</li>\n     *   <li class=\"itm\">Tab-4</li>\n     *   <li class=\"itm\">Tab-5</li>\n     * </ul>\n     * ```\n     *\n     * 脚本示例\n     * ```javascript\n     * NEJ.define([\n     *     'util/query/query',\n     *     'util/tab/tab'\n     * ],function(_e,_t){\n     *     // 使用选择器接口来取列表\n     *     _t._$$Tab._$allocate({\n     *         list:_e._$all('.w-tab > li'),\n     *         onchange:function(_event){\n     *                // TODO\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @method module:util/query/query._$all\n     * @param  {String} arg0 - 选择器\n     * @param  {Node}   arg1 - 用于匹配的根节点，默认为document\n     * @return {Array}         符合规则的节点列表\n     */\n    _p._$all = function(){\n        try{\n            return nes.all.apply(nes,arguments);\n        }catch(e){\n            return null;\n        }\n    };\n    /**\n     * 节点选择器\n     *\n     * 结构示例\n     * ```html\n     * <ul class=\"w-tab\">\n     *   <li class=\"itm\">Tab-0</li>\n     *   <li class=\"itm\">Tab-1</li>\n     *   <li class=\"itm\">Tab-2</li>\n     *   <li class=\"itm js-selected\">Tab-3</li>\n     *   <li class=\"itm\">Tab-4</li>\n     *   <li class=\"itm\">Tab-5</li>\n     * </ul>\n     * ```\n     *\n     * 脚本示例\n     * ```javascript\n     * NEJ.define([\n     *     'util/query/query'\n     * ],function(_t){\n     *     // 使用选择器接口来取选中的节点\n     *     var _node = _t._$one('.w-tab > li.js-selected');\n     * });\n     * ```\n     *\n     * @method module:util/query/query._$one\n     * @param  {String} arg0 - 选择器\n     * @param  {Node}   arg1 - 用于匹配的根节点，默认为document\n     * @return {Node}          符合规则的节点\n     */\n    _p._$one = function(){\n        try{\n            return nes.one.apply(nes,arguments);\n        }catch(e){\n            return null;\n        }\n    };\n    // for test only\n    _p._$g = nes._get;\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.e'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/range/demo/range.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - 范围选择器</title>\n    <meta charset=\"utf-8\" />\n    <style>\n      body{cursor:default;}\n      .pbox{position:relative;width:500px;height:400px;margin:50px;border:1px solid #aaa;}\n      .rngx{position:absolute;top:0;left:0;border:1px solid #aaa;}\n      .rngy{width:0;height:0;overflow:hidden;border:1px solid #fff;}\n    </style>\n  </head>\n  <body>\n    \n    <div class=\"rngx\" id=\"x\">\n      <div class=\"rngy\" id=\"y\">&nbsp;</div>\n    </div>\n    \n    <div class=\"pbox\" id=\"abc\"></div>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            'base/element',\n            '../range.js'\n        ],function(_e,_t){\n            _t._$$Range._$allocate({\n                sbody:'y',\n                pbody:'x',\n                parent:'abc',\n                onbeforechange:function(_event){\n                    _e._$get('abc').appendChild(_e._$get('x'));\n                },\n                onafterchange:function(_event){\n                    _e._$removeByEC('x');\n                },\n                onchange:function(_event){\n                    console.log('top:'+_event.top+' / left:'+_event.left+' / width:'+_event.width+' / height:'+_event.height);\n                }\n            });\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/range/range.js",
    "content": "/*\n * ------------------------------------------\n * 区域大小选择功能封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/range/range */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'base/util',\n    'util/event'\n],function(NEJ,_k,_e,_v,_u,_t,_p,_o,_f,_r,_pro){\n    /**\n     * 区域大小选择功能封装\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"box2\"></div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/range/range'\n     * ],function(_t){\n     *     var _range = _t._$$Range._$allocate({\n     *         sbody:'box2',\n     *         parent:document.body,\n     *         onchange:function(_event){\n     *             // 鼠标移动过程，区域选择过程\n     *         },\n     *         onbeforechange:function(_event){\n     *             // 鼠标按下，区域选择开始\n     *         },\n     *         onafterchange:function(_event){\n     *             // 鼠标放开，区域选择结束\n     *         }\n     *     });\n     * });\n     * ```\n     * \n     * @class    module:util/range/range._$$Range\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object}      config   - 可选配置参数\n     * @property {Node|String} sbody    - 用于改变大小的节点\n     * @property {Node|String} pbody    - 用于改变位置的节点，不传使用sbody\n     * @property {Node|String} parent   - 可选择区域节点\n     * @property {Boolean}     overflow - 是否允许超出parent范围\n     */\n    /**\n     * 区域选择变化触发事件\n     * @event    module:util/range/range._$$Range#onchange \n     * @param    {Object} event  - 范围信息\n     * @property {Number} top    - 上距离\n     * @property {Number} left   - 左距离\n     * @property {Number} width  - 宽\n     * @property {Number} height - 高\n     * @property {Event}  event  - 事件\n     */\n    /**\n     * 区域变化之前触发事件\n     * \n     * @event    module:util/range/range._$$Range#onbeforechange\n     * @param    {Object} event    - 事件\n     * @property {Boolean} stopped - 是否阻止后续逻辑\n     */\n    /**\n     * 区域变化之后触发事件\n     * \n     * @event  module:util/range/range._$$Range#onafterchange\n     */\n    _p._$$Range = _k._$klass();\n    _pro = _p._$$Range._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/range/range._$$Range#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        // init node\n        this.__overflow = !!_options.overflow;\n        this.__sbody = _e._$get(_options.sbody);\n        this.__pbody = _e._$get(_options.pbody)||this.__sbody;\n        this.__parent = _e._$get(_options.parent)||document.body;\n        // init event\n        this.__doInitDomEvent([[\n            document,'mouseup',\n            this.__onRangEnd._$bind(this),\n        ],[\n            document,'mousemove',\n            this.__onRanging._$bind(this)\n        ],[\n            this.__parent,'mousedown',\n            this.__onRangeStart._$bind(this)\n        ]]);\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/range/range._$$Range#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        delete this.__sbody;\n        delete this.__pbody;\n        delete this.__parent;\n        delete this.__offset;\n        delete this.__delta;\n        delete this.__maxbx;\n    };\n    /**\n     * 刷新参考信息\n     * @return {Void}\n     */\n    _pro.__doRefreshBox = function(){\n        this.__delta = _e._$offset(this.__parent);\n        this.__delta.w = this.__pbody.offsetWidth-\n                         this.__sbody.clientWidth;\n        this.__delta.h = this.__pbody.offsetHeight-\n                         this.__sbody.clientHeight;\n        this.__maxbx = {\n            w:this.__parent.clientWidth,\n            h:this.__parent.clientHeight\n        };\n    };\n    /**\n     * 改变范围\n     * \n     * @protected\n     * @method module:util/range/range._$$Range#__doChangeRange\n     * @param  {Object} arg0 - 范围信息\n     * @return {Void}\n     */\n    _pro.__doChangeRange = (function(){\n        var _isEqual = function(_node,_obj){\n            return !_u._$forIn(\n                _obj,function(_value,_name){\n                    return _value!==parseInt(\n                        _e._$getStyle(_node,_name)\n                    );\n                }\n            );\n        };\n        var _doUnit = function(_obj){\n            _u._$forIn(\n                _obj,function(_value,_key,_map){\n                    _map[_key] = _value+'px';\n                }\n            );\n            return _obj;\n        };\n        return function(_event){\n            // adjust box\n            _event.top -= this.__delta.y;\n            _event.left -= this.__delta.x;\n            _event.width = Math.max(0,_event.width-this.__delta.w);\n            _event.height = Math.max(0,_event.height-this.__delta.h);\n            // check limit\n            var _xpos = {top:_event.top,left:_event.left},\n                _size = {width:_event.width,height:_event.height};\n            if (!this.__overflow){\n                // for performance\n                if (_event.top<0&&_event.left<0){\n                    return;\n                }\n                _xpos.top = Math.max(0,_event.top);\n                _xpos.left = Math.max(0,_event.left);\n                if (_event.top>=0){\n                    _size.height = Math.min(\n                        _event.height,\n                        this.__maxbx.h-_xpos.top-this.__delta.h\n                    );\n                }else{\n                    delete _size.height;\n                }\n                if (_event.left>=0){\n                    _size.width = Math.min(\n                        _event.width,\n                        this.__maxbx.w-_xpos.left-this.__delta.w\n                    );\n                }else{\n                    delete _size.width;\n                }\n            }\n            // check changed\n            if (_isEqual(this.__pbody,_xpos)&&\n                _isEqual(this.__sbody,_size)){\n                return;\n            }\n            // update position and size\n            _e._$style(this.__pbody,_doUnit(_xpos));\n            _e._$style(this.__sbody,_doUnit(_size));\n            this._$dispatchEvent(\n                'onchange',this._$getRangeBox()\n            );\n        };\n    })();\n    /**\n     * 开始范围选择\n     * \n     * @protected\n     * @method module:util/range/range._$$Range#__onRangeStart\n     * @param  {Event} arg0 - 事件\n     * @return {Void}\n     */\n    _pro.__onRangeStart = function(_event){\n        // left button only\n        if (!!this.__offset) return;\n        try{\n            _event.stopped = !1;\n            this._$dispatchEvent('onbeforechange',_event);\n            if (!!_event.stopped) return;\n        }catch(ex){\n            // ignore\n        }\n        // record position\n        this.__offset = {\n            x:_v._$pageX(_event),\n            y:_v._$pageY(_event)\n        };\n        // update position\n        this.__doRefreshBox();\n        this.__doChangeRange({\n            width:0,\n            height:0,\n            event:_event,\n            top:this.__offset.y,\n            left:this.__offset.x\n        });\n    };\n    /**\n     * 范围选择过程\n     * \n     * @protected\n     * @method module:util/range/range._$$Range#__onRanging\n     * @param  {Event} arg0 - 事件\n     * @return {Void}\n     */\n    _pro.__onRanging = function(_event){\n        if (!this.__offset) return;\n        // calculate position\n        var _offset = {\n                x:_v._$pageX(_event),\n                y:_v._$pageY(_event)\n            },\n            _delta = {\n                x:_offset.x-this.__offset.x,\n                y:_offset.y-this.__offset.y\n            };\n        // update position\n        this.__doChangeRange({\n            event:_event,\n            width:Math.abs(_delta.x),\n            height:Math.abs(_delta.y),\n            top:_delta.y<0?_offset.y:this.__offset.y,\n            left:_delta.x<0?_offset.x:this.__offset.x\n        });\n    };\n    /**\n     * 结束范围选择\n     * \n     * @protected\n     * @method module:util/range/range._$$Range#__onRangEnd\n     * @param  {Event} arg0 - 事件\n     * @return {Void}\n     */\n    _pro.__onRangEnd = function(_event){\n        if (!!this.__offset){\n            delete this.__offset;\n            this._$dispatchEvent('onafterchange');\n        }\n    };\n    /**\n     * 取选择范围信息\n     * \n     * @method module:util/range/range._$$Range#_$getRangeBox\n     * @return {Object} 选择范围信息\n     */\n    _pro._$getRangeBox = function(){\n        return {\n            width:this.__pbody.offsetWidth,\n            height:this.__pbody.offsetHeight,\n            top:parseInt(_e._$getStyle(this.__pbody,'top')),\n            left:parseInt(_e._$getStyle(this.__pbody,'left'))\n        };\n    };\n    \n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/range/test/range.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>range测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t</head>\n    <body onselectstart=\"return false\">\n        <h1 id=\"qunit-header\">Qunit range test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n\t\t<div id=\"box2\">111</div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./range.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/range/test/range.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"range\");\n    var p = NEJ.P('nej.ut'),\n        e = NEJ.P('nej.e');\n    //开始单元测试\n\ttest('range',function(){\n\t\tstop();\n\t\tvar _box2  = e._$get('box2');\n\t\tvar _rg = p._$$Range._$allocate({\n\t\t\tbody:_box2,\n\t\t\tonchange:function(_event){\n\t\t\t\tok(true,'选择区域');\n\t\t\t},\n\t\t\tonbeforechange:function(_event){\n            },\n\t\t\tonafterchange:function(_event){\n\t\t\t\tok(true,'区域选择完毕');\n\t\t\t\tstart();\n            }\n\t\t});\n\t});\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}range.test.js',['{lib}util/range/range.js'],f);\n});\n  "
  },
  {
    "path": "src/util/region/demo/at.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - 三级联动省市区选择</title>\n    <meta charset=\"utf-8\" />\n  </head>\n  <body>\n    <div>\n      <select id=\"a\"></select>\n      <select id=\"b\"></select>\n      <select id=\"c\"></select>\n    </div>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n     NEJ.define([\n         'util/region/zh',\n         'util/data/region/zh'\n     ],function(_t,_d){\n         var _region = _t._$$RegionSelector._$allocate({\n             province:'a',\n             city:'b',\n             area:'c',\n             data:{province:'浙江省',city:'杭州市',area:'滨江区'},\n             cache:_d._$$CacheRegionZH._$allocate(),\n             onchange:function(_type){\n                 // TODO\n             }\n         });\n     });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/region/region.zh.js",
    "content": "// link to util/region/zh for compatible\n// use util/region/zh for new project \nNEJ.define(['./zh.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/region/test/region.zh.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>regionSelector测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit regionSelector test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n\t\t<div>\n\t\t\t<select id=\"a\"></select>\n\t\t\t<select id=\"b\"></select>\n\t\t\t<select id=\"c\"></select>\n\t\t</div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./region.zh.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/region/test/region.zh.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"regionSelector\");\n    \n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v'),\n        _p = _('nej.ut');\n    \n    test('regionSelector test',function(){\n        expect(0);\n        var _rsr = _p._$$RegionSelector._$allocate({\n\t\t\tprovince:'a',\n\t\t\tcity:'b',\n\t\t\tarea:'c',\n\t\t\tdata:{province:'浙江省',city:'杭州市',area:'滨江区'},\n\t\t\tonchange:function(_type){\n\t\t\t}\n\t\t});\n\t\t_rsr._$setRegion({province:'浙江省',city:'杭州市',area:'下城区'})\n    });\n    //开始单元测试\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}region.zh.test.js',\n    ['{lib}util/data/region/zh.js','{lib}util/region/region.zh.js'],f);\n});\n  "
  },
  {
    "path": "src/util/region/zh.js",
    "content": "/*\n * ------------------------------------------\n * 三级联动区域选择控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/region/zh */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/util',\n    'util/event'\n],function(NEJ,_k,_e,_u,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 三级联动区域选择控件\n     * \n     * 结构举例\n     * ```html\n     * <div>\n     *   <select id=\"a\"></select>\n     *   <select id=\"b\"></select>\n     *   <select id=\"c\"></select>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/region/zh',\n     *     'util/data/region/zh'\n     * ],function(_t,_d){\n     *     var _region = _t._$$RegionSelector._$allocate({\n     *         province:'a',\n     *         city:'b',\n     *         area:'c',\n     *         data:{province:'浙江省',city:'杭州市',area:'滨江区'},\n     *         cache:_d._$$CacheRegionZH._$allocate(),\n     *         onchange:function(_type){\n     *             // 触发3次type，从area到province，搜索条件可能用到\n     *         }\n     *     });\n     * });\n     * ```\n     * \n     * @class   module:util/region/zh._$$RegionSelector\n     * @extends module:util/event._$$EventTarget\n     * \n     * @param    {Object}      config   - 可选配置参数\n     * @property {String|Node} province - 省份选择控件\n     * @property {String|Node} city     - 城市选择控件\n     * @property {String|Node} area     - 地区选择控件\n     * @property {module:util/cache/list._$$CacheList} cache - 数据缓存实例\n     * @property {Object}      data     - 初始地区信息，如{province:'浙江省',city:'杭州市',area:'滨江区'}\n     * @property {module:util/cache/abstract._$$CacheListAbstract} cache - 省市区数据缓存实例，默认可使用util/data/region/zh下的数据\n     */\n    /** \n     * 区域变化触发事件\n     * \n     * @event module:util/region/zh._$$RegionSelector#onchange\n     * @param {String} event - 变化类型(province/city/area)\n     */\n    _p._$$RegionSelector = _k._$klass();\n    _pro = _p._$$RegionSelector._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/region/zh._$$RegionSelector#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__cache = _options.cache;\n        if (!this.__cache) return;\n        var _nmap = {\n            province:_e._$get(_options.province),\n            city:_e._$get(_options.city),\n            area:_e._$get(_options.area)\n        };\n        this.__selectors = _nmap;\n        this.__offset = _nmap.province.options.length||0;\n        this.__doInitDomEvent([\n            [_nmap.area,'change',this.__onChange._$bind(this,'area')]\n           ,[_nmap.city,'change',this.__onChange._$bind(this,'city')]\n           ,[_nmap.province,'change',this.__onChange._$bind(this,'province')]\n        ]);\n        this.__cache._$setEvent(\n            'onlistload',\n            this.__onListLoad._$bind(this)\n        );\n        this.__doClearSelect(_nmap.province);\n        this._$setRegion(_options.data,!0);\n        this.__cache._$getList({key:'province'});\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/region/zh._$$RegionSelector#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        if (!!this.__cache){\n            this.__cache._$recycle();\n            delete this.__cache;\n        }\n        delete this.__cache;\n        delete this.__data;\n        delete this.__selectors;\n    };\n    /**\n     * 清理选择器\n     * \n     * @protected\n     * @method module:util/region/zh._$$RegionSelector#__doClearSelect\n     * @param  {Node} arg0 - 选择器\n     * @return {Void}\n     */\n    _pro.__doClearSelect = function(_selector){\n        if (!!_selector){\n            _selector.options.length = this.__offset;\n        }\n    };\n    /**\n     * 选择器填充数据\n     * \n     * @protected\n     * @method module:util/region/zh._$$RegionSelector#__doFillList\n     * @param  {Node}  arg0 - 选择器\n     * @param  {Array} arg1 - 数据列表\n     * @return {Void}\n     */\n    _pro.__doFillList = function(_selector,_list){\n        if (!_selector) return;\n        _u._$forEach(\n            _list,function(_value){\n                _selector.add(new Option(_value,_value));\n            }\n        );\n        _e._$setStyle(\n            _selector,'display',\n            !_list||!_list.length?'none':''\n        );\n    };\n    /**\n     * 设置值\n     * \n     * @protected\n     * @method module:util/region/zh._$$RegionSelector#__doSetValue\n     * @param  {String} arg0 - 类型\n     * @return {Void}\n     */\n    _pro.__doSetValue = function(_type){\n        var _value = this.__data[_type]||'';\n        if (!!_value){\n            this.__selectors[_type].value = _value;\n            delete this.__data[_type];\n        }\n        this.__onChange(_type);\n    };\n    /**\n     * 选择变化\n     * \n     * @protected\n     * @method module:util/region/zh._$$RegionSelector#__onChange\n     * @param  {String} arg0 - 变化类型，province/city/area\n     * @return {Void}\n     */\n    _pro.__onChange = function(_type){\n        var _nmap = this.__selectors,\n            _value = _nmap.province.value;\n        switch(_type){\n            case 'province':\n                this.__doClearSelect(_nmap.city);\n                this.__doClearSelect(_nmap.area);\n                // init show e.g. municipality\n                if (!this.__cache._$hasArea(_value)){\n                    _e._$setStyle(_nmap.area,'display','none');\n                    if (!_nmap.area){\n                        _e._$setStyle(_nmap.city,'display','none');\n                        break;\n                    }else{\n                        _e._$setStyle(_nmap.city,'display','');\n                    }\n                }else{\n                    _e._$setStyle(_nmap.area,'display','');\n                    _e._$setStyle(_nmap.city,'display','');\n                }\n                // get city list\n                if (!!_nmap.city&&!!_value){\n                    this.__cache._$getList({key:'city-'+_value});\n                }\n            break;\n            case 'city':\n                this.__doClearSelect(_nmap.area);\n                var _city = _nmap.city.value;\n                if (!_city) return;\n                this.__cache._$getList({key:'area-'+_value+'-'+_city});\n            break;\n        }\n        this._$dispatchEvent('onchange',_type);\n    };\n    /**\n     * 区域列表载入回调\n     * \n     * @protected\n     * @method module:util/region/zh._$$RegionSelector#__onListLoad\n     * @param  {Object} arg0 - 列表信息\n     * @return {Void}\n     */\n    _pro.__onListLoad = function(_options){\n        var _key  = _options.key,\n            _type = _key.split('-')[0],\n            _node = this.__selectors[_type];\n        this.__doFillList(\n            _node,this.__cache.\n            _$getListInCache(_key)\n        );\n        this.__doSetValue(_type);\n    };\n    /**\n     * 设置区域信息\n     * \n     * 脚本举例\n     * ```javascript\n     * _region._$setRegion({\n     *     province:'浙江省',\n     *     city:'杭州市',\n     *     area:'下城区'\n     * });\n     * ```\n     * @method module:util/region/zh._$$RegionSelector#_$setRegion\n     * @param    {Object} arg0     - 区域信息，如{province:'浙江省',city:'杭州市',area:'滨江区'}\n     * @property {String} province - 省\n     * @property {String} city     - 市\n     * @property {String} area     - 区\n     * @return   {Void}\n     */\n    _pro._$setRegion = function(_data,_nochange){\n        this.__data = _data||_o;\n        if (!_nochange){\n            this.__doSetValue('province');\n        }\n    };\n    \n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/resize/demo/resize.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - 范围选择器</title>\n    <meta charset=\"utf-8\" />\n    <style>\n      body{background:#FFDDCC;}\n      .parent{position:relative;width:500px;height:300px;margin:50px;border:1px solid #aaa;}\n     .out{position:absolute;border:1px solid #000;}\n     .inr{width:50px;height:50px;border:1px solid #fff;}\n     .inr span{position:absolute;}\n     .lefttop{top:0;left:0;width:5px;height:5px;line-height:5px;background:transparent;z-index:99;cursor:nw-resize;overflow:hidden}\n     .top{top:0;width:100%;height:5px;line-height:5px;background:transparent;z-index:98;cursor:n-resize;overflow:hidden}\n     .righttop{top:0;right:0;width:5px;height:5px;line-height:5px;background:transparent;z-index:99;cursor:ne-resize;overflow:hidden}\n     .right{right:0;width:5px;height:100%;background:transparent;z-index:98;cursor:_e-resize;overflow:hidden}\n     .rightbottom{bottom:0;right:0;width:5px;height:5px;line-height:5px;background:transparent;z-index:99;cursor:se-resize;overflow:hidden}\n     .bottom{bottom:0;width:100%;height:5px;line-height:5px;background:transparent;z-index:98;cursor:s-resize;overflow:hidden}\n     .leftbottom{bottom:0;left:0;width:5px;height:5px;line-height:5px;background:transparent;z-index:99;cursor:sw-resize;overflow:hidden}\n     .left{left:0;width:5px;height:100%;background:transparent;z-index:98;cursor:w-resize;overflow:hidden}\n     .lefttop,.righttop,.rightbottom,.leftbottom{border:1px solid #aaa;}\n    </style>\n  </head>\n  <body>\n      \n      <div class=\"parent\" id=\"parent\">\n         <div class=\"out\" id=\"obox\">\n           <div class=\"inr\" id=\"ibox\">\n             <span class=\"lefttop\">&nbsp;</span>\n             <span class=\"top\">&nbsp;</span>\n             <span class=\"righttop\">&nbsp;</span>\n             <span class=\"right\">&nbsp;</span>\n             <span class=\"rightbottom\">&nbsp;</span>\n             <span class=\"bottom\">&nbsp;</span>\n             <span class=\"leftbottom\">&nbsp;</span>\n             <span class=\"left\">&nbsp;</span>\n           </div>\n         </div>\n      </div>\n      \n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n         NEJ.define([\n             'util/resize/resize'\n         ],function(_t){\n             _t._$$Resize._$allocate({\n                 view:'parent',\n                 body:'obox',\n                 sbody:'ibox',\n                 // 自己传样式\n                 flag:{\n                     1:'top',\n                     2:'right',\n                     3:'bottom',\n                     4:'left',\n                     5:'lefttop',\n                     6:'righttop',\n                     7:'rightbottom',\n                     8:'leftbottom'\n                 },\n                 onresizestart:function(_event){\n                     // TODO\n                     // _event.top\n                     // _event.left\n                     // _event.width\n                     // _event.height\n                 },\n                 onresize: function(_event){\n                     // TODO\n                     // _event.top\n                     // _event.left\n                     // _event.width\n                     // _event.height\n                 },\n                 onresizeend:function(_event){\n                     // TODO\n                     // _event.top\n                     // _event.left\n                     // _event.width\n                     // _event.height\n                 },\n                 onmove:function(_event){\n                     // TODO\n                     // _event.top\n                     // _event.left\n                     // _event.width\n                     // _event.height\n                 }\n             });\n         });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/resize/resize.js",
    "content": "/*\n * ------------------------------------------\n * 区域大小调节功能封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/resize/resize */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/event',\n    'base/element',\n    'base/util',\n    'util/event',\n    'util/dragger/dragger'\n],function(NEJ,_k,_v,_e,_u,_t0,_t1,_p,_o,_f,_r,_pro){\n    /**\n     * 容器大小位置信息对象\n     * @typedef  {Object} module:util/resize/resize._$$Resizable~SizeModel\n     * @property {Number} top    距离上\n     * @property {Number} left   距离左\n     * @property {Number} width  宽\n     * @property {Number} height 高\n     */\n    /**\n     * 区域大小调节功能封装，方位示意图\n     * \n     * ```javascript\n     *    //  5------ 1 ------6\n     *    //  |               |\n     *    //  |               |\n     *    //  4               2\n     *    //  |               |\n     *    //  |               |\n     *    //  8------ 3 ------7\n     * ```\n     * \n     * 各位置对应的手势及样式标识如下表所示：\n     *\n     * | 标识 | 说明 |\n     * | :--- | :--- |\n     * | 1    | 向上改变大小，对应鼠标手型n-resize，默认样式名js-rs-1 |\n     * | 2    | 向右改变大小，对应鼠标手型e-resize，默认样式名js-rs-2 |\n     * | 3    | 向下改变大小，对应鼠标手型s-resize，默认样式名js-rs-3 |\n     * | 4    | 向左改变大小，对应鼠标手型w-resize，默认样式名js-rs-4 |\n     * | 5    | 向左上改变大小，对应鼠标手型nw-resize，默认样式名js-rs-5 |\n     * | 6    | 向右上改变大小，对应鼠标手型ne-resize，默认样式名js-rs-6 |\n     * | 7    | 向右下改变大小，对应鼠标手型se-resize，默认样式名js-rs-7 |\n     * | 8    | 向左下改变大小，对应鼠标手型sw-resize，默认样式名js-rs-8 |\n     * \n     * 样式举例\n     * ```css\n     *   #box{width:500px;height:500px;border:solid 1px #ccc;position:relative;}\n     *   #box span{position:absolute;}\n     *   .lefttop{top:0;left:0;width:5px;height:5px;line-height:5px;background:transparent;z-index:99;cursor:nw-resize;overflow:hidden}\n     *   .top{top:0;width:100%;height:5px;line-height:5px;background:transparent;z-index:98;cursor:n-resize;overflow:hidden}\n     *   .righttop{top:0;right:0;width:5px;height:5px;line-height:5px;background:transparent;z-index:99;cursor:ne-resize;overflow:hidden}\n     *   .right{right:0;width:5px;height:100%;background:transparent;z-index:98;cursor:_e-resize;overflow:hidden}\n     *   .rightbottom{bottom:0;right:0;width:5px;height:5px;line-height:5px;background:transparent;z-index:99;cursor:se-resize;overflow:hidden}\n     *   .bottom{bottom:0;width:100%;height:5px;line-height:5px;background:transparent;z-index:98;cursor:s-resize;overflow:hidden}\n     *   .leftbottom{bottom:0;left:0;width:5px;height:5px;line-height:5px;background:transparent;z-index:99;cursor:sw-resize;overflow:hidden}\n     *   .left{left:0;width:5px;height:100%;background:transparent;z-index:98;cursor:w-resize;overflow:hidden}\n     * ```\n     * \n     * 结构举例\n     * ```html\n     *   <div id=\"box\">\n     *       <span class=\"lefttop\"> </span>\n     *       <span class=\"top\"> </span>\n     *       <span class=\"righttop\"> </span>\n     *       <span class=\"right\"> </span>\n     *       <span class=\"rightbottom\"> </span>\n     *       <span class=\"bottom\"> </span>\n     *       <span class=\"leftbottom\"> </span>\n     *       <span class=\"left\"> </span>\n     *   </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/resize/resize'\n     * ],function(_t){\n     *     _t._$$Resizable._$allocate({\n     *         body:'box',\n     *         // 自己传样式\n     *         flag:{\n     *             1:'top',\n     *             2:'right',\n     *             3:'bottom',\n     *             4:'left',\n     *             5:'lefttop',\n     *             6:'righttop',\n     *             7:'rightbottom',\n     *             8:'leftbottom'\n     *         },\n     *         onresizestart:function(_event){\n     *             // TODO\n     *             // _event.top\n     *             // _event.left\n     *             // _event.width\n     *             // _event.height\n     *         },\n     *         onresize: function(_event){\n     *             // TODO\n     *             // _event.top\n     *             // _event.left\n     *             // _event.width\n     *             // _event.height\n     *         },\n     *         onresizeend:function(_event){\n     *             // TODO\n     *             // _event.top\n     *             // _event.left\n     *             // _event.width\n     *             // _event.height\n     *         },\n     *         onmove:function(_event){\n     *             // TODO\n     *             // _event.top\n     *             // _event.left\n     *             // _event.width\n     *             // _event.height\n     *         }\n     *     });\n     * });\n     * ```\n     * @class   module:util/resize/resize._$$Resizable\n     * @extends module:util/event._$$EventTarget\n     * \n     * @param    {Object}      conifg - 可选配置参数\n     * @property {Node}        view   - 视窗节点，默认为documentElement或body节点\n     * @property {String|Node} body   - 位置变化节点\n     * @property {String|Node} sbody  - 大小变化节点，默认为位置变化节点\n     * @property {Object}      flag   - 各方向节点样式标识\n     * @property {Boolean}     lock   - 是否锁定宽高比\n     * @property {Object}      min    - 最小保留值，{width:50,height:50}\n     */\n    /** \n     * 大小变化开始触发事件\n     * \n     * @event  module:util/resize/resize._$$Resizable#onresizestart\n     * @param {module:util/resize/resize._$$Resizable~SizeModel} event - 事件信息\n     */\n    /** \n     * 大小变化触发事件\n     * \n     * @event  module:util/resize/resize._$$Resizable#onresize\n     * @param {module:util/resize/resize._$$Resizable~SizeModel} event - 事件信息\n     */\n    /** \n     * 大小变化结束触发事件\n     * \n     * @event  module:util/resize/resize._$$Resizable#onresizeend\n     * @param {module:util/resize/resize._$$Resizable~SizeModel} event - 事件信息\n     */\n    /**\n     * 区域移动触发事件\n     * \n     * @event  module:util/resize/resize._$$Resizable#onmove\n     * @param {module:util/resize/resize._$$Resizable~SizeModel} event - 事件信息\n     */\n    _p._$$Resizable = _k._$klass();\n    _pro = _p._$$Resizable._$extend(_t0._$$EventTarget);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/resize/resize._$$Resizable#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        var _min = _options.min||_o;\n        this.__body = _e._$get(_options.body);\n        this.__sbody = _e._$get(_options.sbody)||this.__body;\n        this.__minx = parseInt(_min.width)||20;\n        this.__miny = parseInt(_min.height)||20;\n        this.__view = _e._$get(_options.view)||\n                      _e._$getScrollViewPort(this.__body);\n        if (!!_options.lock){\n            this.__ratio = this.__body.offsetWidth/\n                           this.__body.offsetHeight;\n            var _ratio = this.__minx/this.__miny;\n            if (_ratio<this.__ratio){\n                this.__minx = this.__miny*this.__ratio;\n            }else{\n                this.__miny = this.__minx/this.__ratio;\n            }\n        }\n        this.__doInitNode(_options.flag||_o);\n        this.__dragger = _t1._$$Dragger._$allocate({\n            body:this.__body,\n            view:this.__view,\n            onchange:this.__onResizeMove._$bind(this)\n        });\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/resize/resize._$$Resizable#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        if (!!this.__dragger){\n            this.__dragger._$recycle();\n            delete this.__dragger;\n        }\n        delete this.__body;\n        delete this.__view;\n        delete this.__sbody;\n        this.__super();\n    };\n    /**\n     * 初始化节点\n     * \n     * @protected\n     * @method module:util/resize/resize._$$Resizable#__doInitNode\n     * @param  {Object} arg0 - 样式映射表\n     * @return {Void}\n     */\n    _pro.__doInitNode = function(_class){\n        var _arr = [];\n        for(var i=1,_list,_node;i<9;i++){\n            _list = _e._$getByClassName(\n                this.__body,_class[i]||('js-rs-'+i)\n            );\n            _node = (_list||_o)[0];\n            if (!!_node){\n                _arr.push([\n                    _node,'mousedown',\n                    this.__onResizeStart._$bind2(this,i)\n                ]);\n            }\n        }\n        _arr.push([\n            document,'mouseup',\n            this.__onResizEnd._$bind(this)\n        ]);\n        _arr.push([\n            document,'mousemove',\n            this.__onResizing._$bind(this)\n        ]);\n        _arr.push([\n            this.__body,\n            'selectstart',\n            _v._$stop._$bind(_v)\n        ]);\n        this.__doInitDomEvent(_arr);\n    };\n    /**\n     * 锁定比例计算位置大小信息\n     *\n     * @protected\n     * @method module:util/resize/resize._$$Resizable#__doCalBoxWithLock\n     * @return {Object} 位置大小信息\n     */\n    _pro.__doCalBoxWithLock = function(_event,_delta){\n        switch(this.__flag){\n            // top\n            case 1:\n                var _tmp  = _event.top+_event.height,\n                    _tmp0 = _event.top+_delta.y,\n                    _tmp1 = _tmp-this.__miny,\n                    _tmp2 = _tmp-Math.floor((this.__box.w-\n                            _event.left-this.__delta.x)/this.__ratio);\n                _event.top = Math.min(_tmp1,Math.max(0,_tmp0,_tmp2));\n                _event.height = _tmp-_event.top;\n                _event.width  = Math.floor(_event.height*this.__ratio);\n            break;\n            // right\n            case 2:\n                var _tmp0 = _event.width+_delta.x,\n                    _tmp1 = Math.floor((this.__box.h-\n                           _event.top-this.__delta.y)*this.__ratio),\n                    _tmp2 = this.__box.w-_event.left-this.__delta.x;\n                _event.width = Math.max(this.__minx,Math.min(_tmp0,_tmp1,_tmp2));\n                _event.height = Math.floor(_event.width/this.__ratio);\n            break;\n            // bottom\n            case 3:\n                var _tmp  = _event.left+_event.width,\n                    _tmp0 = _event.height+_delta.y,\n                    _tmp1 = Math.floor(_tmp/this.__ratio),\n                    _tmp2 = this.__box.h-_event.top-this.__delta.y;\n                _event.height = Math.max(this.__miny,Math.min(_tmp0,_tmp1,_tmp2));\n                _event.width  = Math.floor(_event.height*this.__ratio);\n                _event.left = _tmp-_event.width;\n            break;\n            // left\n            case 4:\n                var _tmp  = _event.left+_event.width,\n                    _tmp0 = _event.top+_event.height,\n                    _tmp1 = _event.left+_delta.x,\n                    _tmp2 = _tmp-Math.floor(_tmp0*this.__ratio),\n                    _tmp3 = _tmp-this.__minx;\n                _event.left = Math.max(0,_tmp2,Math.min(_tmp1,_tmp3));\n                _event.width = _tmp-_event.left;\n                _event.height = Math.floor(_event.width/this.__ratio);\n                _event.top = _tmp0-_event.height;\n            break;\n            // left top\n            case 5:\n                var _tmp  = _event.left+_event.width,\n                    _tmp1 = _event.top+_event.height,\n                    _tmp2 = _event.top+_delta.y,\n                    _tmp3 = _tmp1-Math.floor(_tmp/this.__ratio),\n                    _tmp4 = _tmp1-this.__miny;\n                _event.top = Math.max(0,_tmp3,Math.min(_tmp2,_tmp4));\n                _event.height = _tmp1-_event.top;\n                _event.width = Math.floor(_event.height*this.__ratio);\n                _event.left = _tmp-_event.width;\n            break;\n            // right top\n            case 6:\n                var _tmp  = _event.top+_event.height,\n                    _tmp1 = _event.width+_delta.x,\n                    _tmp2 = Math.floor(_tmp*this.__ratio),\n                    _tmp3 = this.__box.w-_event.left-this.__delta.x;\n                _event.width = Math.max(this.__minx,Math.min(_tmp1,_tmp2,_tmp3));\n                _event.height = Math.floor(_event.width/this.__ratio);\n                _event.top = _tmp-_event.height;\n            break;\n            // right bottom\n            case 7:\n                var _tmp1 = _event.height+_delta.y,\n                    _tmp2 = Math.floor((this.__box.w-\n                           _event.left-this.__delta.x)/this.__ratio),\n                    _tmp3 = this.__box.h-_event.top-this.__delta.y;\n                _event.height = Math.max(this.__miny,Math.min(_tmp1,_tmp2,_tmp3));\n                _event.width = Math.floor(_event.height*this.__ratio);\n            break;\n            // left bottom\n            case 8:\n                var _tmp = _event.left+_event.width,\n                    _tmp1 = _event.left+_delta.x,\n                    _tmp2 = _tmp-this.__minx,\n                    _tmp3 = _tmp-Math.floor((this.__box.h-\n                            _event.top-this.__delta.y)*this.__ratio);\n                _event.left = Math.max(0,_tmp3,Math.min(_tmp1,_tmp2));\n                _event.width = _tmp-_event.left;\n                _event.height = Math.floor(_event.width/this.__ratio);\n            break;\n        }\n        return _event;\n    };\n    /**\n     * 不锁定比例计算位置大小信息\n     *\n     * @protected\n     * @method module:util/resize/resize._$$Resizable#__doCalBoxWithoutLock\n     * @return {Object} 位置大小信息\n     */\n    _pro.__doCalBoxWithoutLock = function(_event,_delta){\n        var _tmp;\n        // top\n        if (this.__flag==1||\n            this.__flag==5||\n            this.__flag==6){\n            _tmp = _event.top+_event.height-this.__miny;\n            _event.top = Math.min(_tmp,\n                         Math.max(0,_event.top+_delta.y));\n            _event.height = _tmp+this.__miny-_event.top;\n        }\n        // right\n        if (this.__flag==2||\n            this.__flag==6||\n            this.__flag==7){\n            _event.width = Math.max(this.__minx,\n                           Math.min(_event.width+\n                           _delta.x,this.__box.w-\n                           _event.left-this.__delta.x));\n        }\n        // bottom\n        if (this.__flag==3||\n            this.__flag==7||\n            this.__flag==8){\n            _event.height = Math.max(this.__miny,\n                            Math.min(_event.height+\n                            _delta.y,this.__box.h-\n                            _event.top-this.__delta.y));\n        }\n        // left\n        if (this.__flag==4||\n            this.__flag==5||\n            this.__flag==8){\n            _tmp = _event.left+_event.width-this.__minx;\n            _event.left = Math.min(_tmp,\n                          Math.max(0,_event.left+_delta.x));\n            _event.width = _tmp+this.__minx-_event.left;\n        }\n        return _event;\n    };\n    /**\n     * 开始调整大小触发事件\n     * \n     * @protected\n     * @method module:util/resize/resize._$$Resizable#__onResizeStart\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onResizeStart = (function(){\n        var _cursor = {\n            1:'n-resize',2:'e-resize',\n            3:'s-resize',4:'w-resize',\n            5:'nw-resize',6:'ne-resize',\n            7:'se-resize',8:'sw-resize'\n        };\n        return function(_event,_flag){\n            _v._$stop(_event);\n            this.__flag = _flag;\n            if (!this.__flag||\n                !_cursor[this.__flag]){\n                delete this.__flag;\n                return;\n            }\n            this.__offset = {\n                x:_v._$pageX(_event),\n                y:_v._$pageY(_event)\n            };\n            this.__doRefreshBox();\n            document.body.style.cursor = _cursor[this.__flag];\n            this._$dispatchEvent('onresizestart',this._$getResizeBox());\n        };\n    })();\n    /**\n     * 大小调整过程触发事件\n     * \n     * @protected\n     * @method module:util/resize/resize._$$Resizable#__onResizing\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onResizing = function(_event){\n        if (!this.__flag) return;\n        var _offset = {\n            x:_v._$pageX(_event),\n            y:_v._$pageY(_event)\n        };\n        var _tmp,\n            _delta = {\n                x:_offset.x-this.__offset.x,\n                y:_offset.y-this.__offset.y\n            },\n            _event = {\n                top:parseInt(_e._$getStyle(this.__body,'top'))||0,\n                left:parseInt(_e._$getStyle(this.__body,'left'))||0,\n                width:parseInt(_e._$getStyle(this.__sbody,'width'))||0,\n                height:parseInt(_e._$getStyle(this.__sbody,'height'))||0\n            };\n        this.__offset = _offset;\n        this.__doUpdateSize(_event,_delta);\n    };\n    /**\n     * 结束调整大小触发事件\n     * \n     * @protected\n     * @method module:util/resize/resize._$$Resizable#__onResizEnd\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onResizEnd = function(_event){\n        if (!this.__flag) return;\n        delete this.__box;\n        delete this.__flag;\n        delete this.__delta;\n        delete this.__offset;\n        document.body.style.cursor = '';\n        this._$dispatchEvent('onresizeend',this._$getResizeBox());\n    };\n    /**\n     * 大小区域移动触发事件\n     *\n     * @protected\n     * @method module:util/resize/resize._$$Resizable#__onResizeMove\n     * @return  {Void}\n     */\n    _pro.__onResizeMove = function(_event){\n        this._$dispatchEvent('onmove',this._$getResizeBox());\n    };\n    /**\n     * 刷新容器信息\n     * \n     * @protected\n     * @method module:util/resize/resize._$$Resizable#__doRefreshBox\n     * @return {Void}\n     */\n    _pro.__doRefreshBox = function(){\n        this.__box = {\n            w:Math.max(\n                this.__view.clientWidth,\n                this.__view.scrollWidth\n            ),\n            h:Math.max(\n                this.__view.clientHeight,\n                this.__view.scrollHeight\n            )\n        };\n        this.__delta = {\n            x:this.__body.offsetWidth-\n              this.__sbody.clientWidth,\n            y:this.__body.offsetHeight-\n              this.__sbody.clientHeight\n        };\n    };\n    /**\n     * 更新位置信息\n     * \n     * @protected\n     * @method module:util/resize/resize._$$Resizable#__doUpdateSize\n     * @param  {Object} arg0 - 位置信息\n     * @param  {Object} arg2 - 偏移信息\n     * @return {Void}\n     */\n    _pro.__doUpdateSize = (function(){\n        var _doUpdate = function(_node,_map,_names){\n            _u._$forEach(\n                _names,function(_name){\n                    var _value = _map[_name];\n                    if (_value!=null){\n                        _e._$setStyle(_node,_name,_value+'px');\n                    }\n                }\n            );\n        };\n        var _doRoundValue = function(_event){\n            _u._$loop(_event,function(_value,_key,_map){\n                _map[_key] = Math.round(_value);\n            });\n        };\n        return function(_event,_delta){\n            _event = !this.__ratio\n                   ? this.__doCalBoxWithoutLock(_event,_delta)\n                   : this.__doCalBoxWithLock(_event,_delta);\n            // active style\n            _doRoundValue(_event);\n            this._$dispatchEvent('onbeforeresize',_event);\n            if (!!_event.stopped) return;\n            _doUpdate(\n                this.__body,\n                _event,['top','left']\n            );\n            _doUpdate(\n                this.__sbody,\n                _event,['width','height']\n            );\n            this._$dispatchEvent('onresize',_event);\n        };\n    })();\n    /**\n     * 取区域节点位置大小信息\n     *\n     * @method module:util/resize/resize._$$Resizable#_$getResizeBox\n     * @return {module:util/resize/resize._$$Resizable~SizeModel} 信息\n     */\n    _pro._$getResizeBox = function(){\n        var _style = this.__body.style;\n        return {\n            top:parseInt(_style.top)||0,\n            left:parseInt(_style.left)||0,\n            width:this.__body.offsetWidth,\n            height:this.__body.offsetHeight\n        };\n    };\n    /**\n     * 更新位置信息\n     * \n     * @method module:util/resize/resize._$$Resizable#_$update\n     * @param {module:util/resize/resize._$$Resizable~SizeModel} arg0 - 位置信息\n     */\n    _pro._$update = function(_box){\n        this.__flag = 7;\n        this.__doRefreshBox();\n        this.__doUpdateSize(_box,{x:0,y:0});\n    };\n    // alias for resizable\n    _p._$$Resize = _p._$$Resizable;\n    \n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/resize/test/resize.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>resize测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n        <style type=\"text/css\">\n        \t#box{width:200px;height:200px;border:solid 1px #ccc;position:relative;}\n\t\t\t#box span{position:absolute;}\n\t\t\t.lefttop{top:0;left:0;width:5px;height:5px;line-height:5px;background:transparent;z-index:99;cursor:nw-resize;overflow:hidden}\n\t\t\t.top{top:0;width:100%;height:5px;line-height:5px;background:transparent;z-index:98;cursor:n-resize;overflow:hidden}\n\t\t\t.righttop{top:0;right:0;width:5px;height:5px;line-height:5px;background:transparent;z-index:99;cursor:ne-resize;overflow:hidden}\n\t\t\t.right{right:0;width:5px;height:100%;background:transparent;z-index:98;cursor:e-resize;overflow:hidden}\n\t\t\t.rightbottom{bottom:0;right:0;width:5px;height:5px;line-height:5px;background:transparent;z-index:99;cursor:se-resize;overflow:hidden}\n\t\t\t.bottom{bottom:0;width:100%;height:5px;line-height:5px;background:transparent;z-index:98;cursor:s-resize;overflow:hidden}\n\t\t\t.leftbottom{bottom:0;left:0;width:5px;height:5px;line-height:5px;background:transparent;z-index:99;cursor:sw-resize;overflow:hidden}\n\t\t\t.left{left:0;width:5px;height:100%;background:transparent;z-index:98;cursor:w-resize;overflow:hidden}\n        </style>\n\t</head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit resize test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n\t\t<div id=\"box\">\n\t\t\t<span class=\"lefttop\"> </span>\n\t\t\t<span class=\"top\"> </span>\n\t\t\t<span class=\"righttop\"> </span>\n\t\t\t<span class=\"right\"> </span>\n\t\t\t<span class=\"rightbottom\"> </span>\n\t\t\t<span class=\"bottom\"> </span>\n\t\t\t<span class=\"leftbottom\"> </span>\n\t\t\t<span class=\"left\"> </span>\n\t\t</div>\n\t\t<script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./resize.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/resize/test/resize.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"resize\");\n    var p = NEJ.P('nej.ut'),\n        e = NEJ.P('nej.e');\n    //开始单元测试\n    test('resize',function(){\n        expect(0);\n\t\tp._$$Resize._$allocate({\n\t\t\tbody:e._$get('box'),\n\t\t\tclazz:['','top','right','bottom','left','lefttop','righttop','rightbottom','leftbottom'],\n\t\t\tonresize: function(_value){\n\t\t\t}\n\t\t});\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}resize.test.js',['{lib}util/resize/resize.js'],f);\n});\n  "
  },
  {
    "path": "src/util/scroll/demo/simple.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - 简易自定义滚动条</title>\n    <meta charset=\"utf-8\"/>\n    <style>\n      body{-webkit-user-select:none;-moz-user-select:none;user-select:none;}\n      .xbc{position:relative;width:300px;margin:10px auto;border:1px solid #aaa;}\n      .abc{height:600px;overflow:hidden;}\n      .abc p{height:80px;line-height:80px;}\n      .ty{top:0;bottom:0;right:0;width:10px;height:100%;}\n      .bar{position:absolute;background:#f00;overflow:hidden;cursor:default;}\n      .x{left:0;bottom:0;height:10px;width:50px;}\n      .y{top:0;right:0;width:10px;height:50px;}\n      .trk{position:absolute;background:#aaa;}\n      .trk:hover,.j-hover{width:20px;}\n      .trk:hover .y,.j-hover .y{right:5px;}\n      p{background:#fdc;}\n    </style>\n  </head>\n  <body>\n    <div style=\"height:500px;\">&nbsp;</div>\n    <div class=\"xbc\" id=\"bbox\">\n      <div class=\"bar x\" id=\"xbar\">&nbsp;</div>\n      <div class=\"trk ty\"><div class=\"bar y\" id=\"ybar\">&nbsp;</div></div>\n      <div class=\"abc\" id=\"box\" onclick=\"this.innerHTML='&nbsp;'\" ondblclick=\"fill();\">\n      </div>\n    </div>\n    <div style=\"height:500px;\">&nbsp;</div>\n    <script src=\"../../../define.js?pro=./\"></script>\n    <script>\n        function fill(e){\n            var a = [];\n            for(var i=0;i<100;i++){\n                a.push('<p>'+i+'</p>');\n            }\n            document.getElementById('box').innerHTML = a.join('');\n        }\n        define([\n            'util/scroll/simple'\n        ],function(_t){\n            fill();\n            _t._$$SimpleScroll._$allocate({\n                xbar:{body:'xbar'},\n                ybar:{body:'ybar',track:':parent',hover:'j-hover'},\n                parent:'box',\n                trigger:'bbox'\n            });\n            \n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/scroll/demo/smart.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>test smart scroll</title>\n    <meta charset=\"utf-8\"/>\n    <style>\n      p{margin:200px 0;}\n    </style>\n  </head>\n  <body>\n    <p>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</p>\n    <p>bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb</p>\n    <p>ccccccccccccccccccccccccccccccccccc</p>\n    <p>dddddddddddddddddddddddddddddddddddd</p>\n    <p>eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee</p>\n    <p>fffffffffffffffffffffffffffffffffff</p>\n    <p>ggggggggggggggggggggggggggggggggggggg</p>\n    <p>111111111111111111111111111111</p>\n    <p>222222222222222222222222222</p>\n    <p>33333333333333333333333333333</p>\n    <script src=\"../../../../src/define.js\"></script>\n    <script>\n      define([\n          '../smart.js'\n      ],function(_t){\n          _t._$$SmartScroll._$allocate();\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/scroll/platform/simple.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author\n * ------------------------------------------\n */\nNEJ.define(function(p){\n    /**\n     * 插入回车换行\n     * @param doc\n     * @private\n     */\n    p.__getOverflowParent = function(parent){\n        return parent;\n    };\n});"
  },
  {
    "path": "src/util/scroll/platform/simple.patch.js",
    "content": "/*\n * ------------------------------------------\n * 需要平台适配的接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    './simple.js'\n],function(h){\n    // for ie\n    NEJ.patch('TR',function(){\n        /**\n         * 插入回车换行\n         * @param doc\n         * @private\n         */\n        h.__getOverflowParent = function(parent){\n            var ret = parent;\n            if (ret.tagName=='BODY'){\n                ret = ret.ownerDocument.documentElement;\n            }\n            return ret;\n        };\n    });\n    return h;\n});\n"
  },
  {
    "path": "src/util/scroll/scroll.simple.js",
    "content": "// link to util/scroll/simple for compatible\n// use util/scroll/simple for new project\nNEJ.define(['./simple.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/scroll/simple.js",
    "content": "/**\n * ------------------------------------------\n * 滚动控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/scroll/simple */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'base/util',\n    'util/event',\n    'util/dragger/dragger',\n    'util/animation/easeinout',\n    '{platform}simple.js'\n],function(NEJ,_k,_e,_v,_u,_t,_t0,_t1,_h,_p,_o,_f,_r){\n    // variable declaration\n    var _pro;\n    /**\n     * 滚动控件\n     * \n     * 结构举例\n     * ```html\n     * <div class=\"xbc\" id=\"bbox\">\n     *    <div class=\"bar x\" id=\"xbar\"><!-- 水平滚动条 --></div>\n     *    <div class=\"bar y\" id=\"ybar\"><!-- 垂直滚动条 --></div>\n     *    <div class=\"abc\" id=\"box\">\n     *      <!-- 滚动内容 -->\n     *      <p>11111111111111111</p>\n     *      <p>11111111111111111</p>\n     *      <p>11111111111111111</p>\n     *      <p>11111111111111111</p>\n     *      <p>11111111111111111</p>\n     *    </div>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/event',\n     *     'util/scroll/simple'\n     * ],function(_v,_t){\n     *     // 应用模拟滚动行为\n     *     _t._$$SimpleScroll._$allocate({\n     *         xbar:'xbar',\n     *         // 纵向滚动条至少保留20px高度，上下留5px间隙\n     *         ybar:{body:'ybar',min:20,top:5,bottom:5},\n     *         parent:'box'\n     *     });\n     *\n     *     // 滚动过程可以通过监听parent上的onscroll事件获得\n     *     _v._$addEvent(\n     *         'box','scroll',function(_event){\n     *             var _node = _v._$getElement(_event);\n     *             // get scrollTop from _node.scrollTop\n     *         }\n     *     );\n     * });\n     * ```\n     *\n     * @class    module:util/scroll/simple._$$SimpleScroll\n     * @extends  module:util/event._$$EventTarget\n     *\n     * @param    {Object}       config  - 可选配置参数\n     * @property {Node|Object}  xbar    - 水平滚动条节点或者配置信息，如果不配置min值则默认取body的初始宽度，配置如{body:'bar-id',track:':parent',min:10,speed:1,left:10,right:10,step:10,hover:'js-hover'}\n     * @property {Node|Object}  ybar    - 垂直滚动条节点或者配置信息，如果不配置min值则默认取body的初始高度，配置如{body:'bar-id',track:'parent-id',min:10,speed:1,top:10,bottom:10,step:10,hover:'js-hover'}\n     * @property {String|Node}  parent  - 滚动容器节点，默认为滚动条的父容器，滚动过程触发该节点上的onscroll事件\n     * @property {String|Node}  trigger - 滚动条显示隐藏触点，不传表示不做显示隐藏切换\n     */\n    _p._$$SimpleScroll = _k._$klass();\n    _pro = _p._$$SimpleScroll._$extend(_t._$$EventTarget);\n    /**\n     * 初始化控件\n     * \n     * @protected\n     * @method module:util/scroll/simple._$$SimpleScroll#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__aopt = {\n            to:{},\n            from:{},\n            duration:500,\n            onstop:this.__doStopBarOpacity._$bind(this),\n            onupdate:this.__doUpdateBarOpacity._$bind(this)\n        };\n        this.__dopt = {\n            x:{\n                direction:1,\n                ondragend:this.__onUpdateBarEnd._$bind(this,'x'),\n                onbeforechange:this.__onBeforeUpdateBar._$bind(this,'x')\n            },\n            y:{\n                direction:2,\n                ondragend:this.__onUpdateBarEnd._$bind(this,'y'),\n                onbeforechange:this.__onBeforeUpdateBar._$bind(this,'y')\n            }\n        };\n        this.__dragger = {};\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/scroll/simple._$$SimpleScroll#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = (function(){\n        var _bcnf = {\n            x:{\n                min:0,speed:1,step:50,interval:50,left:0,right:0,\n                hover:'js-hover',sb:'scrollWidth',cb:'clientWidth',ob:'offsetWidth',sr:'scrollLeft',ss:'width',sp:'left',dr:'right'\n            },\n            y:{\n                min:0,speed:1,interval:50,step:50,top:0,bottom:0,\n                hover:'js-hover',sb:'scrollHeight',cb:'clientHeight',ob:'offsetHeight',sr:'scrollTop',ss:'height',sp:'top',dr:'bottom'\n            }\n        };\n        // init scrollbar\n        var _doInitBar = function(_name,_conf){\n            if (!(_conf||_o).body){\n                _conf = {body:_conf};\n            }\n            var _result = NEJ.X(\n                NEJ.X({},_bcnf[_name]),_conf\n            );\n            _result.body = _e._$get(_result.body);\n            if (!!_result.body&&!!_result.track){\n                if (_result.track==':parent'){\n                    _result.track = _result.body.parentNode;\n                }\n                _result.track = _e._$get(_result.track);\n            }\n            if (!_result.min){\n                _result.min = !_result.body?10:(_result.body[_result.ob]||10);\n            }\n            return _result;\n        };\n        var _doInitBarDrag = function(_name,_body){\n            if (!_body) return;\n            var _options = this.__dopt[_name];\n            _options.body = _body;\n            _options.view = this.__parent;\n            this.__dragger[_name] =\n                _t0._$$Dragger._$allocate(_options);\n        };\n        return function(_options){\n            this.__super(_options);\n            this.__bar = {\n                x:_doInitBar('x',_options.xbar),\n                y:_doInitBar('y',_options.ybar)\n            };\n            this.__parent = _e._$get(_options.parent);\n            // init event\n            this.__doInitDomEvent([[\n                this.__parent,'mousewheel',\n                this.__onMouseWheel._$bind(this)\n            ],[\n                this.__parent,'scroll',\n                this.__doSyncScrollBar._$bind(this)\n            ],[\n                this.__parent,'mouseover',\n                this.__doFixScrollBar._$bind(this)\n            ],[\n                this.__bar.x.track,'mousedown',\n                this.__onTrackDown._$bind(this,'x')\n            ],[\n                this.__bar.y.track,'mousedown',\n                this.__onTrackDown._$bind(this,'y')\n            ],[\n                this.__bar.x.track,'mousewheel',\n                this.__onMouseWheel._$bind(this)\n            ],[\n                this.__bar.y.track,'mousewheel',\n                this.__onMouseWheel._$bind(this)\n            ]]);\n            var _node = _e._$get(_options.trigger);\n            if (!!_node){\n                this.__doInitDomEvent([[\n                    _options.trigger,'mouseenter',\n                    this.__onMouseEnter._$bind(this)\n                ],[\n                    _options.trigger,'mouseleave',\n                    this.__onMouseLeave._$bind(this)\n                ]]);\n                this.__doUpdateBarOpacity({offset:0});\n            }else{\n                this._$resize();\n            }\n            // init dragdrop\n            _doInitBarDrag.call(\n                this,'x',this.__bar.x.body\n            );\n            _doInitBarDrag.call(\n                this,'y',this.__bar.y.body\n            );\n        };\n    })();\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/scroll/simple._$$SimpleScroll#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = (function(){\n        var _doClearDragger = function(_dragger,_key,_map){\n            _dragger._$recycle();\n            delete _map[_key];\n            var _conf = this.__dopt[_key];\n            delete _conf.view;\n            delete _conf.body;\n        };\n        var _doClearBarStyle = function(_conf,_key,_map){\n            if (!_conf.body) return;\n            var _style = {};\n            _style[_conf.ss] = '';\n            _style[_conf.sp] = '';\n            _e._$style(_conf.body,_style);\n            delete _conf.body;\n        };\n        return function(){\n            this.__super();\n            delete this.__isout;\n            delete this.__parent;\n            delete this.__dragging;\n            this.__doStopBarOpacity();\n            _u._$loop(\n                this.__dragger,\n                _doClearDragger._$bind(this)\n            );\n            _u._$loop(\n                this.__bar,\n                _doClearBarStyle._$bind(this)\n            );\n            delete this.__bar;\n        };\n    })();\n    /**\n     * 取滚动条容器节点\n     * @private\n     */\n    _pro.__getOverflowParent = function(){\n        return _h.__getOverflowParent(this.__parent);\n    };\n    /**\n     * 根据配置信息重置滚动条\n     *\n     * @protected\n     * @method module:util/scroll/simple._$$SimpleScroll#__doResetBarSize\n     * @param  {Object} arg0 - 配置信息\n     * @return {Void}\n     */\n    _pro.__doResetBarSize = function(_conf){\n        var _parent = this.__getOverflowParent(),\n            _sbox = _parent[_conf.sb],\n            _cbox = _parent[_conf.cb],\n            _sdlt = _sbox-_cbox,\n            _cbox = _cbox-_conf[_conf.sp]\n                    -_conf[_conf.dr],\n            _delta = _sbox-_cbox,\n            _style = {},\n            _oshow = {};\n        if (_sdlt<=0){\n            _conf.ratio = 0;\n            _oshow.visibility = 'hidden';\n            _style[_conf.ss] = _cbox+'px';\n        }else{\n            var _size = Math.ceil(Math.max(\n                _conf.min,\n                _cbox-_cbox/_sbox*_delta\n            ));\n            _oshow.visibility = 'visible';\n            _style[_conf.ss] = _size+'px';\n            _conf.max = Math.ceil(\n                _cbox-_size+\n                _conf[_conf.sp]\n            );\n            _conf.ratio = (_cbox-_size)/_delta;\n        }\n        _conf.delta = 0;\n        if (!!_conf.body){\n            _conf.delta =\n                _conf.body[_conf.ob]-\n                _conf.body[_conf.cb];\n        }\n        _e._$style(_conf.track||_conf.body,_oshow);\n        _e._$style(_conf.body,_style);\n    };\n    /**\n     * 重置滚动条位置\n     *\n     * @protected\n     * @method module:util/scroll/simple._$$SimpleScroll#__doResetBarPosition\n     * @param  {Object} arg0 - 配置信息\n     * @param  {Number} arg1 - 偏移量\n     * @return {Void}\n     */\n    _pro.__doResetBarPosition = function(_conf,_delta){\n        var _parent = this.__getOverflowParent();\n        if (_delta!=0){\n            _parent[_conf.sr] -= _delta*_conf.speed;\n        }\n        if (!!_conf.body){\n            var _value = _parent[_conf.sr],\n                _offset = Math.ceil(_value*_conf.ratio)-\n                         _conf.delta+_conf[_conf.sp];\n            _e._$setStyle(_conf.body,_conf.sp,_offset+'px');\n        }\n    };\n    /**\n     * 同步滚动条位置\n     *\n     * @protected\n     * @method module:util/scroll/simple._$$SimpleScroll#__doSyncScrollBar\n     * @return {Void}\n     */\n    _pro.__doSyncScrollBar = function(){\n        if (!this.__dragging){\n            this._$resize();\n        }\n    };\n    /**\n     * 更新滚动位置\n     *\n     * @protected\n     * @method module:util/scroll/simple._$$SimpleScroll#__doUpdateScrollBar\n     * @return {Void}\n     */\n    _pro.__doUpdateScrollBar = function(_dx,_dy){\n        this.__doResetBarPosition(\n            this.__bar.y,_dy\n        );\n        this.__doResetBarPosition(\n            this.__bar.x,_dx\n        );\n    };\n    /**\n     * 动画更新滚动条透明度\n     *\n     * @protected\n     * @method module:util/scroll/simple._$$SimpleScroll#__doAnimScrollBar\n     * @return {Void}\n     */\n    _pro.__doAnimScrollBar = function(){\n        this.__doStopBarOpacity();\n        var _tmp = this.__bar.y,\n            _body = _tmp.track||_tmp.body;\n        if (!_body){\n            _tmp = this.__bar.x;\n            _body = _tmp.track||_tmp.body;\n        }\n        this.__aopt.from.offset = _e._$getStyle(\n            _body,'opacity'\n        );\n        this.__anim = _t1._$$AnimEaseInOut.\n                      _$allocate(this.__aopt);\n        this.__anim._$play();\n    };\n    /**\n     * 更新滚动条的透明度\n     *\n     * @protected\n     * @method module:util/scroll/simple._$$SimpleScroll#__doUpdateBarOpacity\n     * @return {Void}\n     */\n    _pro.__doUpdateBarOpacity = function(_event){\n        var _value = _event.offset;\n        _e._$setStyle(\n            this.__bar.x.track||\n            this.__bar.x.body,\n            'opacity',_value\n        );\n        _e._$setStyle(\n            this.__bar.y.track||\n            this.__bar.y.body,\n            'opacity',_value\n        );\n    };\n    /**\n     * 清理显示动画\n     *\n     * @protected\n     * @method module:util/scroll/simple._$$SimpleScroll#__doStopBarOpacity\n     * @return {Void}\n     */\n    _pro.__doStopBarOpacity = function(){\n        if (!!this.__anim){\n            this.__anim._$recycle();\n            delete this.__anim;\n        }\n    };\n    /**\n     * 鼠标滚动事件\n     *\n     * @protected\n     * @method module:util/scroll/simple._$$SimpleScroll#__onMouseWheel\n     * @param  {Event} 事件信息\n     * @return {Void}\n     */\n    _pro.__onMouseWheel = function(_event){\n        var _parent = this.__getOverflowParent(),\n            _dt = _parent.scrollTop,\n            _dl = _parent.scrollLeft;\n        // update scroll bar\n        this.__doUpdateScrollBar(\n            _event.wheelDeltaX||0,\n            _event.wheelDeltaY||\n            _event.wheelDelta||0\n        );\n        // check end\n        _dt = _parent.scrollTop!=_dt;\n        _dl = _parent.scrollLeft!=_dl;\n        if (_dt||_dl){\n            _v._$stop(_event);\n        }\n    };\n    /**\n     * 鼠标移入事件\n     *\n     * @protected\n     * @method module:util/scroll/simple._$$SimpleScroll#__onMouseEnter\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onMouseEnter = function(_event){\n        this.__isout = !1;\n        this._$resize();\n        this.__aopt.delay = 0;\n        this.__aopt.to.offset = 0.6;\n        this.__doAnimScrollBar();\n    };\n    /**\n     * 鼠标移出事件\n     *\n     * @protected\n     * @method module:util/scroll/simple._$$SimpleScroll#__onMouseLeave\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onMouseLeave = function(_event){\n        this.__isout = !0;\n        if (this.__dragging) return;\n        this.__aopt.delay = 500;\n        this.__aopt.to.offset = 0;\n        this.__doAnimScrollBar();\n    };\n    /**\n     * 轨道点击事件\n     *\n     * @protected\n     * @method module:util/scroll/simple._$$SimpleScroll#__onTrackDown\n     * @param  {String} arg0 - 类型\n     * @param  {Event}  arg1 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onTrackDown = (function(){\n        var _fmap = {\n            x:function(_delta){\n                this.__doUpdateScrollBar(_delta,0);\n            },\n            y:function(_delta){\n                this.__doUpdateScrollBar(0,_delta);\n            }\n        };\n        var _timer,_onstop,_count;\n        var _doClearScroll = function(_conf){\n            _count = 1;\n            _onstop = null;\n            _timer = window.clearTimeout(_timer);\n            _v._$delEvent(_conf.track,'mouseup',_onstop);\n        };\n        var _doAutoScroll = function(_type,_point,_size){\n            var _conf = this.__bar[_type],\n                _left = parseInt(_e._$getStyle(\n                    _conf.body,_conf.sp\n                )),\n                _right = _left+_size;\n            // stop scroll\n            if (_left<=_point&&_point<=_right){\n                _doClearScroll(_conf);\n                return;\n            }\n            // init stop event\n            if (!_onstop){\n                _onstop = _doClearScroll._$bind(this,_conf);\n                _v._$addEvent(_conf.track,'mouseup',_onstop);\n            }\n            // update scrollbar\n            _fmap[_type].call(this,(_point<_left?1:-1)*_conf.step*_count);\n            // next scrollbar\n            _timer = window.setTimeout(\n                _doAutoScroll._$bind(this,_type,_point,_size),\n                _conf.interval\n            );\n            _count++;\n        };\n        return function(_type,_event){\n            var _conf = this.__bar[_type],\n                _offset = _e._$offset(_conf.track)[_type],\n                _pointer = _v._$page(_event)[_type],\n                _size = _conf.body[_conf.ob];\n            _doClearScroll(_conf);\n            _doAutoScroll.call(\n                 this,_type,\n                _pointer-_offset,_size\n            );\n        };\n    })();\n    /**\n     * 更新水平滚动条\n     *\n     * @protected\n     * @method module:util/scroll/simple._$$SimpleScroll#__onBeforeUpdateBar\n     * @param  {Object} arg0 - 拖拽信息\n     * @return {Void}\n     */\n    _pro.__onBeforeUpdateBar = function(_name,_event){\n        this.__dragging = !0;\n        var _parent = this.__getOverflowParent(),\n            _conf = this.__bar[_name],\n            _delta = _conf[_conf.sp],\n            _offset = Math.max(\n                _delta,Math.min(\n                    _conf.max,\n                    _event[_conf.sp]\n                )\n            );\n        _parent[_conf.sr] = Math.ceil(\n            (_offset-_delta)/_conf.ratio\n        );\n        _event[_conf.sp] = _offset;\n        _e._$addClassName(\n            _conf.track,_conf.hover\n        );\n    };\n    /**\n     * 拖拽滚动结束\n     *\n     * @protected\n     * @method module:util/scroll/simple._$$SimpleScroll#__onUpdateBarEnd\n     * @return {Void}\n     */\n    _pro.__onUpdateBarEnd = function(_name){\n        this.__dragging = !1;\n        if (this.__isout){\n            this.__onMouseLeave();\n        }\n        var _conf = this.__bar[_name];\n        _e._$delClassName(\n            _conf.track,_conf.hover\n        );\n    };\n    /**\n     * 修正滚动条状态\n     */\n    _pro.__doFixScrollBar = function(_event){\n        //console.log('fix scrollbar');\n        this._$resize();\n    };\n    /**\n     * 容器大小变化执行逻辑\n     *\n     * @method module:util/scroll/simple._$$SimpleScroll#_$resize\n     * @return {Void}\n     */\n    _pro._$resize = function(){\n        this.__doResetBarSize(this.__bar.x);\n        this.__doResetBarSize(this.__bar.y);\n        this.__doUpdateScrollBar(0,0);\n    };\n    /**\n     * 尝试显示滚动条\n     *\n     * @method module:util/scroll/simple._$$SimpleScroll#_$show\n     * @private\n     */\n    _pro._$show = function(){\n        this.__onMouseEnter();\n    };\n    /**\n     * 尝试隐藏滚动条\n     *\n     * @method module:util/scroll/simple._$$SimpleScroll#_$hide\n     * @private\n     */\n    _pro._$hide = function(){\n        this.__onMouseLeave();\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/scroll/smart.js",
    "content": "/*\n * ------------------------------------------\n * 自动滚动机制实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/scroll/smart */\nNEJ.define([\n    'base/klass',\n    'base/event',\n    'base/element',\n    'util/event'\n],function(_k,_v,_e,_t,_p,_o,_f,_r,_pro){\n    /**\n     * 自动滚动控件\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"box\">\n     *   <p>aaaaaaaaaaaaaaa</p>\n     *   <p>aaaaaaaaaaaaaaa</p>\n     *   <p>aaaaaaaaaaaaaaa</p>\n     *   <p>aaaaaaaaaaaaaaa</p>\n     *   <p>aaaaaaaaaaaaaaa</p>\n     *   <p>aaaaaaaaaaaaaaa</p>\n     *   <p>aaaaaaaaaaaaaaa</p>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/scroll/smart'\n     * ],function(_t){\n     *     var _scroll = _t._$$SmartScroll._$allocate({\n     *         viewport:'box',\n     *         onscrollcheck:function(_event){\n     *             // _event.stopped - 是否禁止自动滚动\n     *         }\n     *     });\n     * });\n     * ```\n     * \n     * @class    module:util/scroll/smart._$$SmartScroll\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object} config    - 可选配置参数\n     * @property {Node}   viewport  - 滚动容器，默认为根结点\n     * @property {Number} step      - 滚动步进，默认50\n     * @property {Array}  range     - 自动滚动临界范围定义，[lower,upper]，鼠标位置均相对于viewport，如\n     *                                [10,200]  - 表示小于10时向上滚，大于200时向下滚\n     *                                [10,-10]  - 值为负数，表示小于10时向上滚，大于viewport可视区高度减10时向下滚\n     *                                [0.1,0.9] - 值在0-1之间，表示小于viewport可视区高度*0.1时向上滚，大于viewport可视区高度*0.9时向下滚\n     * @property {Array}  limit     - 上下限制区域，0表示无限制，如[10,100]，表示viewport可视区上面保留10像素，下面保留100像素\n     */\n    _p._$$SmartScroll = _k._$klass();\n    _pro = _p._$$SmartScroll._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     * @param {Object} _options\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        var _port = _e._$get(_options.viewport);\n        this.__viewport = _port||_e._$getScrollViewPort();\n        this.__step = parseInt(_options.step)||50;\n        this.__rtmp = _options.range;\n        this.__doUpdateLimit(_options.limit);\n        // init event\n        this.__doInitDomEvent([[\n            _port||document,'mousemove',\n            this.__onScrollCheck._$bind(this)\n        ],[\n            document,'mouseup',\n            this.__doStopScroll._$bind(this)\n        ]]);\n    };\n    /**\n     * 控件销毁\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        this.__doStopScroll();\n        delete this.__rtmp;\n        delete this.__range;\n        delete this.__limit;\n        delete this.__viewport;\n    };\n    /**\n     * 更新限制区域\n     * @return {Void}\n     */\n    _pro.__doUpdateLimit = function(_limit){\n        var _height = this.__viewport.scrollHeight;\n        _limit = _limit||_r;\n        this.__limit = [\n            _limit[0]||0,\n            _limit[1]||0\n        ];\n    };\n    /**\n     * 更新临界位置信息\n     * @return {Void}\n     */\n    _pro.__doUpdateRange = (function(){\n        var _doFormat = function(_value,_height,_default){\n            _value = parseInt(_value)||_default;\n            if (_value<0){\n                return _height+_value;\n            }\n            if (0<_value&&_value<1){\n                return Math.floor(_height*_value);\n            }\n            return _value;\n        };\n        return function(_range){\n            var _xrng = this.__rtmp||_r,\n                _height = this.__viewport.clientHeight,\n                _lower = _doFormat(_xrng[0],_height,0.2),\n                _upper = _doFormat(_xrng[1],_height,0.8);\n            this.__range = [\n                Math.min(_lower,_upper),\n                Math.max(_lower,_upper)\n            ];\n            delete this.__rtmp;\n        };\n    })();\n    /**\n     * 自动滚动\n     * @return {Void}\n     */\n    _pro.__doAutoScroll = function(_flag){\n        if (!_flag){\n            this.__doStopScroll();\n            return;\n        }\n        this.__flag = _flag;\n        if (!this.__timer){\n            this.__timer = window.setInterval(\n                this.__doAutoScrollStep._$bind(this),\n                1000/50\n            );\n        }\n    };\n    /**\n     * 自动滚动\n     * @return {Void}\n     */\n    _pro.__doAutoScrollStep = function(){\n        this.__count = (this.__count||0)+1;\n        var _value = this.__viewport.scrollTop\n                   + this.__flag*Math.min(\n                         this.__step,this.__count\n                     );\n        if (this.__flag<0){\n            // up with min\n            this.__viewport.scrollTop = Math.max(\n                this.__limit[0],_value\n            );\n        }else{\n            // down with max\n            this.__viewport.scrollTop = Math.min(\n                this.__viewport.scrollHeight-this.__limit[1],_value\n            );\n        }\n    };\n    /**\n     * 停止滚动检测\n     * @param {Object} _event\n     */\n    _pro.__doStopScroll = function(){\n        delete this.__flag;\n        delete this.__count;\n        this.__timer = window.clearInterval(this.__timer);\n    };\n    /**\n     * 滚动检测\n     * @param {Object} _event\n     */\n    _pro.__onScrollCheck = function(_evt){\n        var _event = {};\n        this._$dispatchEvent(\n            'onscrollcheck',_event\n        );\n        if (!!_event.stopped){\n            this.__doStopScroll();\n            return;\n        }\n        if (!this.__range){\n            this.__doUpdateRange();\n        }\n        var _range = this.__range,\n            _delta = _v._$clientY(_evt)\n                   - _e._$offset(this.__viewport).y;\n        this.__doAutoScroll(\n            _delta<=_range[0]?-1:(\n                _delta>=_range[1]?1:0\n            )\n        );\n    };\n});\n\n\n"
  },
  {
    "path": "src/util/selector/cascade.js",
    "content": "/*\n * ------------------------------------------\n * 多级级联选择控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/selector/cascade */\nNEJ.define([\n    'base/klass',\n    'base/util',\n    'base/event',\n    'base/element',\n    'util/event'\n],function(_k,_u,_v,_e,_t,_p,_o,_f,_r,_pro){\n    /**\n     * 多级级联选择控件\n     * \n     * 结构举例\n     * ```html\n     * <!-- 这里通过data-value设置默认选中的值 -->\n     * <select id=\"level-1\" name=\"a\" data-value=\"1\"></select>\n     * <select id=\"level-2\" name=\"b\" data-value=\"2\"></select>\n     * <select id=\"level-3\" name=\"c\" data-value=\"22\"></select>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/selector/cascade'\n     * ],function(_t){\n     *     var _selector = _t._$$CascadeSelector._$allocate({\n     *         select:['level-1','level-2','level-3'],\n     *         data:[\n     *             {\n     *                 id:1,\n     *                 name:'l1-1',\n     *                 list:[\n     *                     {\n     *                         id:1,\n     *                         name:'l21-1',\n     *                         list:[\n     *                             {\n     *                                 id:11,\n     *                                 name:'l31-1'\n     *                             },{\n     *                                 id:12,\n     *                                 name:'l31-2'\n     *                             },{\n     *                                 id:13,\n     *                                 name:'l31-3'\n     *                             }\n     *                         ]\n     *                     },{\n     *                         id:2,\n     *                         name:'l22-1',\n     *                         list:[\n     *                             {\n     *                                 id:21,\n     *                                 name:'l32-1'\n     *                             },{\n     *                                 id:22,\n     *                                 name:'l32-2'\n     *                             },{\n     *                                 id:23,\n     *                                 name:'l32-3'\n     *                             }\n     *                         ]\n     *                     }\n     *                 ]\n     *             }\n     *         ],\n     *         onchange:function(_event){\n     *             // 这里的a，b，c为select节点上的name\n     *             // 如果没有设置name则取id作为标识\n     *             log(_event.a+' - '+_event.b+' - '+_event.c);\n     *         }\n     *     });\n     * });\n     * ```\n     * \n     * @class    module:util/selector/cascade._$$CascadeSelector\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object} config - 可选配置参数\n     * @property {Array}  select - 选择节点列表\n     * @property {Object} data   - 级联数据信息\n     * @property {Object} keys   - 数据标识配置，默认{id:'id',text:'name',list:'list'}\n     */\n    /** \n     * 选中变化触发事件\n     * \n     * @event module:util/selector/cascade._$$CascadeSelector#onchange\n     * @param {Object} event - 事件信息，遍历select节点，将name/value组成对象导出\n     */\n    _p._$$CascadeSelector = _k._$klass();\n    _pro = _p._$$CascadeSelector._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/selector/cascade._$$CascadeSelector#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = (function(){\n        var _conf = {\n            id:'id',\n            text:'name',\n            list:'list'\n        };\n        return function(_options){\n            this.__super(_options);\n            this.__conf = _u._$merge(\n                {},_conf,_options.keys\n            );\n            this.__nselect = [];\n            this.__noffset = [];\n            var _arr = [],\n                _default = [];\n            _u._$forEach(\n                _options.select,function(_id,_index){\n                    var _node = _e._$get(_id);\n                    this.__nselect.push(_node);\n                    this.__noffset.push(_node.options.length);\n                    _default.push(_e._$dataset(_id,'value'));\n                    _arr.push([\n                        _id,'change',\n                        this.__onChange._$bind(this,_index)\n                    ]);\n                },this\n            );\n            this.__doInitDomEvent(_arr);\n            this.__doFormatData(_options.data||_r);\n            this._$update(_default);\n        };\n    })();\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/selector/cascade._$$CascadeSelector#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        this.__conf = null;\n        this.__data = null;\n        this.__lock = null;\n        this.__default = null;\n        this.__nselect = null;\n    };\n    /**\n     * 格式化数据列表\n     * \n     * @protected\n     * @method module:util/selector/cascade._$$CascadeSelector#__doFormatData\n     * @param  {Array} arg0 - 数据列表\n     * @return {Void}\n     */\n    _pro.__doFormatData = (function(){\n        var _dump = function(_dmap,_list,_level,_id){\n            _dmap[_level+'-'+(_id||'')] = _list;\n            _u._$forEach(\n                _list,function(_item){\n                    var _xlst = _item[this.__conf.list];\n                    if (!_xlst) return;\n                    _dump.call(\n                        this,_dmap,_xlst,\n                        _level+1,_item[this.__conf.id]\n                    );\n                },this\n            );\n        };\n        return function(_list){\n            this.__data = {};\n            _dump.call(this,this.__data,_list,0);\n        };\n    })();\n    /**\n     * 清空数据列表\n     * \n     * @protected\n     * @method module:util/selector/cascade._$$CascadeSelector#__doClearList\n     * @param  {Node}   arg0 - 选择节点\n     * @return {Void}\n     */\n    _pro.__doClearList = function(_node){\n        if (!_node) return;\n        var _offset = this.__noffset[\n            _u._$indexOf(this.__nselect,_node)\n        ];\n        _u._$reverseEach(\n            _node.options,function(_item,_index){\n                if (_index<_offset){\n                    return !0;\n                }\n                _node.remove(_index);\n            }\n        );\n    };\n    /**\n     * 刷新数据列表\n     * \n     * @protected\n     * @method module:util/selector/cascade._$$CascadeSelector#__doRefreshList\n     * @param  {Node}   arg0 - 选择节点\n     * @param  {Array}  arg1 - 数据列表\n     * @param  {String} arg2 - 默认值\n     * @return {Void}\n     */\n    _pro.__doRefreshList = function(_node,_list,_value){\n        if (!_node) return;\n        this.__doClearList(_node);\n        _u._$forEach(\n            _list,function(_item){\n                var _option = new Option(\n                    _item[this.__conf.text],\n                    _item[this.__conf.id]\n                );\n                _node.add(_option);\n                if (!!_value&&_value==_option.value){\n                    _option.selected = !0;\n                }\n            },this\n        );\n    };\n    /**\n     * 触发变化事件\n     * \n     * @protected\n     * @method module:util/selector/cascade._$$CascadeSelector#__doEmitChangeEvent\n     * @return {Void}\n     */\n    _pro.__doEmitChangeEvent = function(){\n        var _event = {},\n            _lock = [];\n        _u._$forEach(\n            this.__nselect,function(_node){\n                _lock.push(_node.value);\n                _event[_node.name||_node.id] = _node.value;\n            }\n        );\n        _lock = _lock.join('\\n');\n        if (_lock!=this.__lock){\n            this.__lock = _lock;\n            this._$dispatchEvent('onchange',_event);\n        }\n    };\n    /**\n     * 选项变化事件\n     * \n     * @protected\n     * @method module:util/selector/cascade._$$CascadeSelector#__onChange\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onChange = function(_level){\n        // dump next level and list\n        var _next = _level+1,_list;\n        if (_level<0){\n            _list = this.__data['0-'];\n        }else{\n            var _node = this.__nselect[_level];\n            _list = this.__data[_next+'-'+_node.value];\n        }\n        // check list\n        if (!_list||!_list.length){\n            // set sub select un-visible\n            for(var i=_next,l=this.__nselect.length,_it,_dt;i<l;i++){\n                _it = this.__nselect[i];\n                this.__doClearList(_it);\n                _dt = this.__noffset[i];\n                if (!_dt){\n                    _e._$setStyle(_it,'visibility','hidden');\n                }\n            }\n        }else{\n            // refresh sub select list\n            var _node = this.__nselect[_next];\n            if (!!_node){\n                _e._$setStyle(_node,'visibility','visible');\n                this.__doRefreshList(\n                    _node,_list,this.__default[_next]\n                );\n                this.__default[_next] = null;\n                this.__onChange(_next);\n            }\n        }\n        this.__doEmitChangeEvent();\n    };\n    /**\n     * 更新选中值\n     *\n     * 脚本举例\n     * ```javascript\n     * _selector._$update([1,2,22]);\n     * ```\n     * \n     * @method module:util/selector/cascade._$$CascadeSelector#_$update\n     * @param  {Array} arg0 - 根据层级依次设置的值\n     * @return {Void}\n     */\n    _pro._$update = function(_value){\n        this.__default = _value||[];\n        this.__onChange(-1);\n    };\n\n\n    return _p;\n});"
  },
  {
    "path": "src/util/selector/demo/cascade.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>demo for cascade</title>\n    <meta charset=\"utf-8\" />\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n  </head>\n  <body>\n    <select id=\"level-1\" name=\"a\" data-value=\"1\">\n        <option value=\"\">全部</option>\n    </select>\n    <select id=\"level-2\" name=\"b\" data-value=\"2\">\n        <option value=\"\">全部</option>\n    </select>\n    <select id=\"level-3\" name=\"c\" data-value=\"22\">\n        <option value=\"\">全部</option>\n    </select>\n    <script src=\"../../../define.js\"></script>\n    <script>\n      NEJ.define([\n          '../cascade.js'\n      ],function(_t){\n          _t._$$CascadeSelector._$allocate({\n              select:['level-1','level-2','level-3'],\n              data:[\n                  {\n                      id:1,\n                      name:'l1-1',\n                      list:[\n                          {\n                              id:1,\n                              name:'l21-1',\n                              list:[\n                                  {\n                                      id:11,\n                                      name:'l31-1'\n                                  },{\n                                      id:12,\n                                      name:'l31-2'\n                                  },{\n                                      id:13,\n                                      name:'l31-3'\n                                  }\n                              ]\n                          },{\n                              id:2,\n                              name:'l22-1',\n                              list:[\n                                  {\n                                      id:21,\n                                      name:'l32-1'\n                                  },{\n                                      id:22,\n                                      name:'l32-2'\n                                  },{\n                                      id:23,\n                                      name:'l32-3'\n                                  }\n                              ]\n                          }\n                      ]\n                  }\n              ],\n              onchange:function(_event){\n                  log(_event.a+' - '+_event.b+' - '+_event.c);\n              }\n          });\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/selector/demo/selector.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>demo for cascade</title>\n    <meta charset=\"utf-8\" />\n    <style>\n        .mbox{width:240px;padding:5px;border:1px solid #aaa;overflow:hidden;}\n        .mbox .itm{float:left;width:50px;height:50px;background:#fdc;margin:5px;cursor:default;}\n        .mbox .js-selected{background:#0C32F6;}\n    </style>\n    <script>\n      function log(m){\n          var p = document.createElement('p');\n          p.innerHTML = m;\n          document.body.appendChild(p);\n      }\n    </script>\n  </head>\n  <body>\n    <div class=\"mbox\" id=\"list-box\">\n        <div class=\"itm\" data-id=\"1\">1</div>\n        <div class=\"itm\" data-id=\"2\">2</div>\n        <div class=\"itm\" data-id=\"3\">3</div>\n        <div class=\"itm\" data-id=\"4\">4</div>\n        <div class=\"itm\" data-id=\"5\">5</div>\n        <div class=\"itm\" data-id=\"6\">6</div>\n        <div class=\"itm\" data-id=\"7\">7</div>\n        <div class=\"itm\" data-id=\"8\">8</div>\n        <div class=\"itm\" data-id=\"9\">9</div>\n        <div class=\"itm\" data-id=\"a\">a</div>\n    </div>\n    <script src=\"../../../define.js\"></script>\n    <script>\n      NEJ.define([\n          '../selector.js'\n      ],function(_t){\n            _t._$$MultiSelector._$allocate({\n                parent:'list-box',\n                item:'itm',\n                onchange:function(){\n                    //log(JSON.stringify(this._$getSelection()));\n                }\n            });\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/selector/range.js",
    "content": "/*\n * ------------------------------------------\n * 多选控件带范围选择实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** util/selector/range */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/util',\n    'util/selector/selector'\n],function(NEJ,_k,_e,_u,_t0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 多选控件带范围选择\n     *\n     * 页面结构举例\n     * ```html\n     * <body onselectstart=\"return false;\">\n     *  <div id=\"box\"></div>\n     *  <div id=\"box2\"></div>\n     * </body>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/element',\n     *     'base/event',\n     *     'util/selector/range',\n     *     'util/range/range'\n     * ],function(_e,_v,_t0,_t1,_p,_o,_f,_r){\n     *     var _html_seed = _e._$add('{list 1..31 as x}\\\n     *         <div class=\"item\">${x}</div>\\\n     *     {/list}');\n     *     var _box  = _e._$get('box');\n     *     _box.innerHTML = _e._$get(_html_seed);\n     *     var _box2 = _e._$get('box2');\n     *     // 先实例化一个范围选择器\n     *     var _range = _t1._$$Range._$allocate({\n     *         body:_box2,\n     *         onchange:function(_event){\n     *         },\n     *         onbeforechange:function(_event){\n     *         },\n     *         onafterchange:function(_event){\n     *         }\n     *     });\n     *     // 能被选中的节点，是parent节点下，所有样式为item的节点\n     *     // 上面的范围选择器可以不传onchange，这个事件下面会处理，鼠标移动时触发\n     *     // 监听范围选择器的的onchange事件，在事件里断节点是否在范围内，加上select的样式\n     *     _t0._$$RangeSelector._$allocate({\n     *         parent:box,\n     *         range:_range,\n     *         item:'item',\n     *         select:'select',\n     *         onchange:function(_event){\n     *             // 鼠标down，开始选择的回调\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @class    module:util/selector/range._$$RangeSelector\n     * @extends  module:util/selector/selector._$$MultiSelector\n     * @param    {Object} arg0 - 可选配置参数\n     * @property {module:util/range/range._$$Range|module:ui/range/range._$$Range} range - 范围选择器实例\n     */\n    _p._$$RangeSelector = _k._$klass();\n    _pro = _p._$$RangeSelector._$extend(_t0._$$MultiSelector);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/selector/range._$$RangeSelector#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__range = _options.range;\n        if (!this.__range) return;\n        this.__range._$setEvent('onchange',\n             this.__onRangeChange._$bind(this));\n        this.__range._$setEvent('onafterchange',\n             this.__onAfterRangeChange._$bind(this));\n        this.__doRefreshListPosition();\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/selector/range._$$RangeSelector#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = (function(){\n        var _clear = function(_item){\n            _u._$safeDelete(_item,['box','last']);\n        };\n        return function(){\n            _u._$forEach(this.__list,_clear);\n            this.__super();\n            this.__range._$setEvent('onchange',_f);\n            delete this.__range;\n        };\n    })();\n    /**\n     * 判断两个位置是否存在交集\n     *\n     * @protected\n     * @method module:util/selector/range._$$RangeSelector#__hasInterSection\n     * @param  {Object} arg0 -  位置\n     * @param  {Object} arg0 -  位置\n     * @return {Boolean} 交集\n     */\n    _pro.__hasInterSection = function(_pos0,_pos1){\n        return Math.max(_pos0.left,_pos1.left)<\n               Math.min(_pos0.left+_pos0.width,\n                        _pos1.left+_pos1.width)&&\n               Math.max(_pos0.top,_pos1.top)<\n               Math.min(_pos0.top+_pos0.height,\n                        _pos1.top+_pos1.height);\n    };\n    /**\n     * 刷新列表位置信息\n     *\n     * @protected\n     * @method module:util/selector/range._$$RangeSelector#__doRefreshListPosition\n     * @return {Void}\n     */\n    _pro.__doRefreshListPosition = (function(){\n        var _calculate = function(_item){\n            var _offset = _e._$offset(_item);\n            _item.box = {\n                top:_offset.y\n               ,left:_offset.x\n               ,width:_item.offsetWidth\n               ,height:_item.offsetHeight\n            };\n        };\n        return function(){\n            _u._$forEach(this.__list,_calculate);\n        };\n    })();\n    /**\n     * 刷洗节点选择状态\n     *\n     * @protected\n     * @method module:util/selector/range._$$RangeSelector#__doRefreshItemSelect\n     * @param    {Event}   event - 事件对象\n     * @param    {Object}  arg1  - 节点\n     * @property {Boolean} last  - 是否末尾节点\n     * @return   {Void}\n     */\n    _pro.__doRefreshItemSelect = function(_event,_item){\n        var _id = _item.flag,\n            _ctrl = _event.ctrlKey,\n            _shift = _event.shiftKey,\n            _mixed = this.__hasInterSection(\n                          _item.box,_event),\n            _selected = this.__isItemSelected(_id);\n        if (_item.last==null)\n            _item.last = _selected;\n        if (_mixed){\n            _ctrl&&_item.last\n            ? this.__doItemDelFromSelection(_id,_item)\n            : this.__doItemAddToSelection(_id,_item);\n            if (!_ctrl&&_shift) _item.last = !1;\n        }else{\n            _item.last\n            ? this.__doItemAddToSelection(_id,_item)\n            : this.__doItemDelFromSelection(_id,_item);\n        }\n    };\n    /**\n     * 调整最后选中项\n     *\n     * @protected\n     * @method module:util/selector/range._$$RangeSelector#__doAdjustLastItem\n     * @param  {Node} arg0 - 节点\n     * @return {Void}\n     */\n    _pro.__doAdjustLastItem = function(_item){\n        _u._$safeDelete(_item,'last');\n        var _id = _item.flag;\n        if (this.__last<0&&\n            this.__isItemSelected(_id))\n            this.__last = _id;\n    };\n    /**\n     * 范围变化触发事件\n     *\n     * @protected\n     * @method module:util/selector/range._$$RangeSelector#__onRangeChange\n     * @param  {Event} event - 事件对象\n     * @return {Void}\n     */\n    _pro.__onRangeChange = function(_event){\n        // selection clear first\n        _event.ctrlKey = _event.event.ctrlKey;\n        _event.shiftKey = _event.event.shiftKey;\n        delete _event.event;\n        window.setTimeout(\n             _u._$forEach._$bind(_u,this.__list,this\n              .__doRefreshItemSelect._$bind(this,_event)),0);\n    };\n    /**\n     * 区域变化结束事件\n     *\n     * @protected\n     * @method module:util/selector/range._$$RangeSelector#__onAfterRangeChange\n     * @return {Void}\n     */\n    _pro.__onAfterRangeChange = function(){\n        _u._$forEach(this.__list,this.__doAdjustLastItem,this);\n    };\n\n    if (CMPT){\n    \tNEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/selector/selector.js",
    "content": "/*\n * ------------------------------------------\n * 多选控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/selector/selector */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/event',\n    'base/element',\n    'base/util',\n    'util/event'\n],function(NEJ,_k,_v,_e,_u,_t,_p,_o,_f,_r){\n    var _tkey = 'test-'+(+new Date),\n        _pro;\n    /**\n     * 多选控件\n     *\n     * 样式举例\n     * ```css\n     * .itm{width:30px;height:30px;border:solid 1px #ccc;}\n     * .js-selected{background:pink;}\n     * ```\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"box\">\n     *   <div class=\"itm\" data-id=\"0\">&nbsp;</div>\n     *   <div class=\"itm\" data-id=\"1\">&nbsp;</div>\n     *   <div class=\"itm\" data-id=\"2\">&nbsp;</div>\n     *   <div class=\"itm\" data-id=\"3\">&nbsp;</div>\n     *   <div class=\"itm\" data-id=\"4\">&nbsp;</div>\n     *   <div class=\"itm\" data-id=\"5\">&nbsp;</div>\n     *   <div class=\"itm\" data-id=\"6\">&nbsp;</div>\n     *   <div class=\"itm\" data-id=\"7\">&nbsp;</div>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/selector/selector'\n     * ],function(_t){\n     *     var _selector = _t._$$MultiSelector._$allocate({\n     *         parent:'box',\n     *         item:'itm',\n     *         onchange:function(_event){\n     *             var _selection = this._$getSelection();\n     *             \n     *             // TODO something\n     *         }\n     *     });\n     * });\n     * ```\n     * @class    module:util/selector/selector._$$MultiSelector\n     * @extends  module:util/event._$$EventTarget\n     * @param    {Object}      event    - 可选配置参数\n     * @property {Node|String} parent   - 容器节点或者ID，如果不输入则在列表的每一项上检测事件\n     * @property {String}      name     - 项标识属性名称，默认id，节点通过data-id指定项标识\n     * @property {String}      item     - 可选节点样式标识，默认为js-item\n     * @property {String}      selected - 选中样式，默认为js-selected\n     */\n    /** \n     * 选中变化触发事件\n     * \n     * @event module:util/selector/selector._$$MultiSelector#onchange\n     */\n    _p._$$MultiSelector = _k._$klass();\n    _pro = _p._$$MultiSelector._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/selector/selector._$$MultiSelector#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__last = _tkey;\n        this.__selection = {count:0};\n        this.__kname = _options.name||'id';\n        this.__kfcls = _options.item||'js-item';\n        this.__parent = _e._$get(_options.parent);\n        this.__selected = _options.selected||'js-selected';\n        this.__list = _e._$getByClassName(\n            this.__parent,this.__kfcls\n        );\n        // init dom event\n        this.__parent.tabIndex = 10000;\n        this.__doInitDomEvent([[\n            this.__parent,'keydown',\n            this.__onItemSelectAll._$bind(this)\n        ],[\n            this.__parent,'mouseup',\n            this.__onItemSelect._$bind(this)\n        ],[\n            this.__parent,'mousedown',\n            this.__onItemSelectCheck._$bind(this)\n        ]]);\n        // init selection\n        _u._$forEach(\n            this.__list,function(_node){\n                if (_e._$hasClassName(_node,this.__selected))\n                    this.__doItemAddToSelection(\n                        _e._$dataset(_node,this.__kname),_node\n                    );\n            },this\n        );\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/selector/selector._$$MultiSelector#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        this.__doItemClear();\n        delete this.__last;\n        delete this.__list;\n        delete this.__parent;\n        delete this.__selected;\n        delete this.__selection;\n    };\n    /**\n     * 判断节点是否被选中\n     * \n     * @protected\n     * @method module:util/selector/selector._$$MultiSelector#__isItemSelected\n     * @param  {String}  arg0 - 节点标识\n     * @return {Boolean}        是否选中\n     */\n    _pro.__isItemSelected = function(_id){\n        return !!this.__selection[_id];\n    };\n    /**\n     * 选中节点\n     * \n     * @protected\n     * @method module:util/selector/selector._$$MultiSelector#__doItemAddToSelection\n     * @param  {String} arg0 - 节点标识\n     * @param  {Node}   arg1 - 节点对象\n     * @return {Void}\n     */\n    _pro.__doItemAddToSelection = function(_id,_element){\n        if (!!this.__selection[_id]) return;\n        _e._$addClassName(_element,this.__selected);\n        this.__selection[_id] = _e._$id(_element);\n        this.__selection.count++;\n    };\n    /**\n     * 反选节点\n     * \n     * @protected\n     * @method module:util/selector/selector._$$MultiSelector#__doItemDelFromSelection\n     * @param  {String} arg0 - 节点标识\n     * @param  {Node}   arg1 - 节点对象\n     * @return {Void}\n     */\n    _pro.__doItemDelFromSelection = function(_id,_element){\n        if (!this.__selection[_id]) return;\n        _e._$delClassName(_element,this.__selected);\n        delete this.__selection[_id];\n        this.__selection.count--;\n    };\n    /**\n     * 清除选中项\n     * \n     * @protected\n     * @method module:util/selector/selector._$$MultiSelector#__doItemClear\n     * @param  {String} arg0 - 保留节点ID\n     * @return {Void}\n     */\n    _pro.__doItemClear = function(_id){\n        _u._$loop(\n            this.__selection,\n            function(_node,_key){\n                if (_key==_id||\n                    _key=='list'||\n                    _key=='count')\n                    return;\n                this.__doItemDelFromSelection(_key,_node);\n            },this\n        );\n    };\n    /**\n     * 清除选中项\n     * \n     * @protected\n     * @method module:util/selector/selector._$$MultiSelector#__onItemClear\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onItemClear = function(_event){\n        if (_event.ctrlKey||\n            _event.shiftKey)\n            return;\n        this.__doItemClear();\n    };\n    /**\n     * 选择项\n     * \n     * @protected\n     * @method module:util/selector/selector._$$MultiSelector#__onItemSelect\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onItemSelect = function(_event){\n        // check element\n        var _element = _v._$getElement(\n            _event,'c:'+this.__kfcls\n        );\n        if (!_element) return;\n        _v._$stopBubble(_event);\n        var _ctrl = _event.ctrlKey,\n            _shift = _event.shiftKey,\n            _id = _e._$dataset(_element,this.__kname);\n        // right click\n        if (_event.button==2&&\n            this.__isItemSelected(_id))\n            return;\n        // not ctrl and shift\n        if (!_ctrl&&!_shift){\n            this.__doItemClear(_id);\n            this.__doItemAddToSelection(_id,_element);\n        }\n        // ctrl\n        if (_ctrl){\n            ! this.__isItemSelected(_id)\n            ? this.__doItemAddToSelection(_id,_element)\n            : this.__doItemDelFromSelection(_id,_element);\n        }\n        // shift\n        if (_shift){\n            var _last,_test,\n                _selected = !1,\n                _last = this.__last!=_tkey?this.__last:\n                        _e._$dataset(this.__list[0],this.__kname);\n            _u._$forEach(\n                this.__list,\n                function(_item,_index,_list){\n                    var _key = _e._$dataset(_item,this.__kname);\n                    _test = _key==_last||_key==_id;\n                    if (_last!=_id&&_test) \n                        _selected = !_selected;\n                    if (_selected||_test){\n                        this.__doItemAddToSelection(_key,_item);\n                    }else if(!_ctrl){\n                        this.__doItemDelFromSelection(_key,_item);\n                    }\n                },this\n            );\n        }\n        if (!_shift){\n            this.__last = _id;\n        }\n        this.__doSelectionChange();\n    };\n    /**\n     * 检查元素选中情况\n     *\n     * @protected\n     * @method module:util/selector/selector._$$MultiSelector#__onItemSelectCheck\n     * @return {Void}\n     */\n    _pro.__onItemSelectCheck = function(_event){\n        // check element\n        var _element = _v._$getElement(\n            _event,'c:'+this.__kfcls\n        );\n        if (!_element) return;\n        _v._$stopBubble(_event);\n        var _id = _e._$dataset(_element,this.__kname);\n        // not ctrl and shift\n        if (!_event.ctrlKey&&\n            !_event.shiftKey&&\n            !this.__isItemSelected(_id)){\n            this.__doItemClear(_id);\n            this.__doItemAddToSelection(_id,_element);\n            this.__doSelectionChange();\n        }\n    };\n    /**\n     * 全选\n     * \n     * @protected\n     * @method module:util/selector/selector._$$MultiSelector#__onItemSelectAll\n     * @param  {Event} arg0 - 事件对象\n     * @return {Void}\n     */\n    _pro.__onItemSelectAll = function(_event){\n        if (!_event.ctrlKey||\n             _event.keyCode!=65) \n            return;\n        _u._$forEach(\n            this.__list,\n            function(_node){\n                this.__doItemAddToSelection(\n                    _e._$dataset(_node,this.__kname),_node\n                );\n            },this\n        );\n        this.__doSelectionChange();\n    };\n    /**\n     * 选项变化事件\n     *\n     * @protected\n     * @method module:util/selector/selector._$$MultiSelector#__doSelectionChange\n     * @return {Void}\n     */\n    _pro.__doSelectionChange = function(){\n        try{\n            // remove selection if multi-select\n            if (this.__selection.count>1){\n                if (!!document.getSelection){\n                    document.getSelection().collapse(document,0);\n                }else if(!!document.selection){\n                    document.selection.empty();\n                }\n            }\n        }catch(ex){\n            // ignore\n        }\n        this._$dispatchEvent('onchange');\n    };\n    /**\n     * 清除选中\n     * \n     * 脚本举例\n     * ```javascript\n     *   // 清除所有选中状态\n     *   _selector._$clear();\n     * ```\n     * @method module:util/selector/selector._$$MultiSelector#_$clear\n     * @return {Void}\n     */\n    _pro._$clear = function(){\n        this.__doItemClear();\n        this.__doSelectionChange();\n    };\n    /**\n     * 取选项列表\n     * \n     * 脚本举例\n     * ```javascript\n     *   // 获取所有节点列表\n     *   _selector._$getList();\n     * ```\n     * \n     * @method module:util/selector/selector._$$MultiSelector#_$getList\n     * @return {Array} 列表\n     */\n    _pro._$getList = function(){\n        return this.__list;\n    };\n    /**\n     * 取当前选中信息\n     * \n     * 脚本举例\n     * ```javascript\n     *   // 获取被选中的节点列表\n     *   _selector._$getSelection();\n     * ```\n     * \n     * @method module:util/selector/selector._$$MultiSelector#_$getSelection\n     * @param  {Boolean} arg0 - 是否需要排序\n     * @return {Object}         当前选中信息\n     */\n    _pro._$getSelection = function(_sorted){\n        var _result = _u._$merge({},this.__selection);\n        if (!!_sorted){\n            _list = [];\n            _u._$forEach(\n                this.__list,\n                function(_node){\n                    var _id = _e._$dataset(_node,this.__kname);\n                    if (this.__isItemSelected(_id)) _list.push(_id);\n                },this\n            );\n            _result.list = _list;\n        }\n        return _result;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/selector/selector.range.js",
    "content": "// link to util/slector/range for compatible\n// use util/slector/range for new project\nNEJ.define(['./range.js'],function(_t){return _t;});"
  },
  {
    "path": "src/util/slider/demo/simple.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - 简易滑块</title>\n    <meta charset=\"utf-8\" />\n    \n    <style>\n        .track{width:300px;background:#aaa;}\n        .pogrs{position:relative;height:20px;background:#f00;width:30%;}\n        .thumb{position:absolute;top:-5px;right:-5px;width:10px;height:30px;background:#0b0;}\n    </style>\n    \n  </head>\n  <body>\n    \n    <div class=\"track\" id=\"track\">\n      <div class=\"pogrs\" id=\"progress\">\n        <span class=\"thumb\" id=\"thumb\">&nbsp;</span>\n      </div>\n    </div>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            'util/slider/simple'\n        ],function(_t){\n            _t._$$SimpleSlider._$allocate({\n                track:'track',\n                thumb:'thumb',\n                progress:'progress',\n                onslidechange:function(_event){\n                    console.log(_event.ratio);\n                },\n                onslidestop:function(_event){\n                    console.log(_event.ratio);\n                }\n            });\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/slider/demo/y.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <title>NEJ实例 - 简易滑块</title>\n    <meta charset=\"utf-8\" />\n\n    <style>\n        .xxx{position:relative;height:100px;margin:200px 0;padding-top:100px;overflow: auto;}\n        .track{position:relative;height:300px;width:10px;background:#aaa;}\n        .thumb{position:absolute;top:0;left:0;width:10px;height:10px;background:#0b0;}\n    </style>\n\n</head>\n<body>\n\n<div class=\"xxx\">\n    <div class=\"track\" id=\"track\">\n        <span class=\"thumb\" id=\"thumb\">&nbsp;</span>\n    </div>\n</div>\n\n\n<script src=\"../../../define.js\"></script>\n<script>\n    NEJ.define([\n        'util/slider/y'\n    ],function(_t){\n        _t._$$SliderY._$allocate({\n            track:'track',\n            thumb:'thumb',\n            onchange:function(_event){\n                console.log(_event);\n            }\n        });\n    });\n</script>\n</body>\n</html>"
  },
  {
    "path": "src/util/slider/simple.js",
    "content": "/*\n * --------------------------------------------\n * 简易滑块控件实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * --------------------------------------------\n */\n/** @module util/slider/simple */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'util/event'\n],function(NEJ,_k,_e,_v,_t,_p,_o,_f,_r){\n    // variable\n    var _pro;\n    /**\n     * 简易滑块控件，通过控制进度的长度调整滑块位置\n     * \n     * 样式举例\n     * ```css\n     * .track{width:300px;background:#aaa;}\n     * .pogrs{position:relative;height:20px;background:#f00;width:30%;}\n     * .thumb{position:absolute;top:-5px;right:-5px;width:10px;height:30px;background:#0b0;}\n     * ```\n     * \n     * 结构举例\n     * ```html\n     * <div class=\"track\" id=\"track\">\n     *   <div class=\"pogrs\" id=\"progress\">\n     *     <span class=\"thumb\" id=\"thumb\">&nbsp;</span>\n     *   </div>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/slider/simple'\n     * ],function(_t){\n     *     _t._$$SimpleSlider._$allocate({\n     *         track:'track',\n     *         thumb:'thumb',\n     *         progress:'progress',\n     *         onslidechange:function(_event){\n     *             console.log(_event.ratio);\n     *         },\n     *         onslidestop:function(_event){\n     *             console.log(_event.ratio);\n     *         }\n     *     });\n     * });\n     * ```\n     * \n     * @class   module:util/slider/simple._$$SimpleSlider\n     * @extends module:util/event._$$EventTarget\n     *\n     * @param    {Object}      config   - 配置参数\n     * @property {String|Node} track    - 轨道\n     * @property {String|Node} thumb    - 滑块\n     * @property {String|Node} progress - 进度条\n     * @property {Float}       value    - 初始值\n     * @property {Number}      delta    - 数据计算偏差\n     * @property {Boolean}     reset    - 回收时是否重置位置\n     */\n    /**\n     * 滑动过程事件\n     * \n     * @event    module:util/slider/simple._$$SimpleSlider#onslidechange\n     * @param    {Object} event - 滑动信息\n     * @property {Float}  ratio - 滑动比例\n     */\n    /**\n     * 滑动停止事件\n     * \n     * @event    module:util/slider/simple._$$SimpleSlider#onslidestop\n     * @param    {Object} event - 滑动信息\n     * @property {Float}  ratio - 滑动比例\n     *\n     */\n    _p._$$SimpleSlider = _k._$klass();\n    _pro = _p._$$SimpleSlider._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/slider/simple._$$SimpleSlider#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__ndrst = !!_options.reset;\n        this.__delta = parseInt(_options.delta)||0;\n        this.__track = _e._$get(_options.track);\n        this.__prgrs = _e._$get(_options.progress);\n        this.__doInitDomEvent([[\n            _options.thumb,'mousedown',\n            this.__onSlideStart._$bind(this)\n        ],[\n            document,'mousemove',\n            this.__onSliding._$bind(this)\n        ],[\n            document,'mouseup',\n            this.__onSlideStop._$bind(this)\n        ],[\n            this.__track,'mousedown',\n            this.__onSlideTo._$bind(this)\n        ]]);\n        // init value\n        var _ratio = _options.value;\n        if (_ratio==null){\n            _ratio = this.__prgrs.offsetWidth/\n                     this.__track.offsetWidth;\n        }\n        this._$setPosition(_ratio);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/slider/simple._$$SimpleSlider#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        if (!!this.__ndrst){\n            this.__doUpdatePosition(0);\n        }\n        this.__super();\n    };\n    /**\n     * 滑动开始\n     *\n     * @protected \n     * @method module:util/slider/simple._$$SimpleSlider#__onSlideStart\n     * @param  {Event} arg0 - 事件信息\n     * @return {Void}\n     */\n    _pro.__onSlideStart = function(_event){\n        if (!!this.__offset) return;\n        _v._$stop(_event);\n        this.__offset = _v._$pageX(_event);\n        this.__owidth = this.__track.offsetWidth;\n    };\n    /**\n     * 滑动过程\n     *\n     * @protected\n     * @method module:util/slider/simple._$$SimpleSlider#__onSliding\n     * @param  {Event} arg0 - 事件信息\n     * @return {Void}\n     */\n    _pro.__onSliding = function(_event){\n        if (!this.__offset) return;\n        var _offset = _v._$pageX(_event),\n            _delta = _offset-this.__offset;\n        this.__offset = _offset;\n        this.__doUpdatePosition(\n            this.__ratio+_delta/this.__owidth\n        );\n        this._$dispatchEvent('onslidechange',{\n            ratio:this.__ratio\n        });\n    };\n    /**\n     * 滑动结束\n     *\n     * @protected\n     * @method module:util/slider/simple._$$SimpleSlider#__onSlideStop\n     * @param  {Event} arg0 - 事件信息\n     * @return {Void}\n     */\n    _pro.__onSlideStop = function(_event){\n        if (!this.__offset) return;\n        this.__onSliding(_event);\n        delete this.__offset;\n        delete this.__owidth;\n        this._$dispatchEvent('onslidestop',{\n            ratio:this.__ratio\n        });\n    };\n    /**\n     * 直接点击跳转至指定位置\n     *\n     * @protected \n     * @method module:util/slider/simple._$$SimpleSlider#__onSlideTo\n     * @return {Void}\n     */\n    _pro.__onSlideTo = function(_event){\n        var _ofstx = _e._$offset(this.__track).x,\n            _pagex = _v._$pageX(_event);\n        this.__doUpdatePosition(\n            (_pagex-_ofstx+this.__delta)/this.__track.offsetWidth\n        );\n        this._$dispatchEvent('onslidestop',{\n            ratio:this.__ratio\n        });\n    };\n    /**\n     * 设置滑块位置\n     *\n     * @protected\n     * @method module:util/slider/simple._$$SimpleSlider#__doUpdatePosition\n     * @param  {Float} arg0 - 滑块百分比\n     * @return {Void}\n     */\n    _pro.__doUpdatePosition = function(_ratio){\n        this.__ratio = Math.max(0,\n                       Math.min(1,_ratio));\n        _e._$setStyle(\n            this.__prgrs,'width',\n            this.__ratio*100+'%'\n        );\n    };\n    /**\n     * 设置滑块位置\n     *\n     * @method module:util/slider/simple._$$SimpleSlider#_$setPosition\n     * @param  {Float} arg0 - 滑块百分比\n     * @return {Void}\n     */\n    _pro._$setPosition = function(_ratio){\n        if (!!this.__offset) return;\n        this.__doUpdatePosition(_ratio);\n    };\n    /**\n     * 取滑块位置\n     *\n     * @method module:util/slider/simple._$$SimpleSlider#_$getPosition\n     * @return {Float} 滑块百分比\n     */\n    _pro._$getPosition = function(_ratio){\n        return this.__ratio;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/slider/slider.js",
    "content": "/*\n * ------------------------------------------\n * 滑动器算法实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/slider/slider */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/event',\n    'util/event',\n    'util/dragger/simple'\n],function(NEJ,_k,_e,_v,_t,_t0,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 滑动器算法\n     *\n     * 样式举例\n     * ```css\n     * #slide{position:absolute;top:0;height:20px;line-height:20px;width:20px;background:green;}\n     * #track{position:relative;height:20px;line-height:20px;width:100%;background:pink;}\n     * ```\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"track\">\n     *   <div id=\"slide\">&nbsp;</div>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/slider/slider'\n     * ],function(_t){\n     *     var _slider = _t._$$Slider._$allocate({\n     *         range:{x:[0,100]},\n     *         slide:'slide',\n     *         track:'track',\n     *         onchange:function(_obj){\n     *             _e._$style('slide',{left:_obj.x.value});\n     *         }\n     *     });\n     * });\n     * ```\n     * @class    module:util/slider/slider._$$Slider\n     * @extends  module:util/event._$$EventTarget\n     * @param    {Object}      config    - 可选配置参数\n     * @property {Object}      range     - 滑动范围，默认为滑块可运动范围，如{x:[0,100],y:[0,1000]}\n     * @property {String|Node} thumb     - 滑块节点\n     * @property {String|Node} track     - 滑动轨道节点\n     * @property {Number}      direction - 滑动方向控制，0 - 水平垂直[默认]，1 - 水平，2 - 垂直\n     */\n    /**\n     * 滑动触发事件，输入格式如{x:{rate:0.4,value:40},y:{rate:0.5,value:50}}\n     * \n     * @event    module:util/slider/slider._$$Slider#onchange\n     * @param    {Object}  event   - 滑动信息\n     * @property {Boolean} stopped - 是否停止\n     * @property {Object}  x       - 水平滑动信息，如{rate:0.4,value:40}\n     * @property {Object}  y       - 垂直滑动信息，如{rate:0.5,value:50}\n     *\n     */\n    _p._$$Slider = _k._$klass();\n    _pro = _p._$$Slider._$extend(_t._$$EventTarget);\n    /**\n     * 控件初始化\n     * \n     * @protected\n     * @method module:util/slider/slider._$$Slider#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__dopt = {\n            onchange:this.__onChange._$bind(this),\n            ondragend:this.__onChange._$bind2(this,!0)\n        };\n        this.__super();\n    };\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/slider/slider._$$Slider#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__dopt.view = _e._$get(_options.track);\n        this.__dopt.body = _e._$get(_options.thumb)||\n                           _e._$get(_options.slide);\n        this.__dopt.mbar = this.__dopt.view;\n        this.__dopt.direction = parseInt(_options.direction)||0;\n        this._$setRange(_options.range);\n        this.__doInitDomEvent([[\n            this.__dopt.view,'mousedown',\n            this.__onSlideToPosition._$bind(this)\n        ]]);\n        this.__dragger = _t0._$$Dragger._$allocate(this.__dopt);\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/slider/slider._$$Slider#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        this.__dragger._$recycle();\n        delete this.__dragger;\n        delete this.__range;\n        delete this.__dopt.view;\n        delete this.__dopt.body;\n        delete this.__dopt.mbar;\n    };\n    /**\n     * 活动过程触发事件\n     * \n     * @protected\n     * @method module:util/slider/slider._$$Slider#__onChange\n     * @param  {Object} arg0 - 位置信息\n     * @return {Void}\n     */\n    _pro.__onChange = function(_event,_end){\n        var _ratex = _event.left/this.__range.x[1],\n            _ratey = _event.top/this.__range.y[1],\n            _rngx = this.__range.x,\n            _rngy = this.__range.y;\n        this._$dispatchEvent('onchange',{\n            stopped:!!_end,\n            x:{rate:_ratex,value:_ratex*(_rngx[1]-_rngx[0])},\n            y:{rate:_ratey,value:_ratey*(_rngy[1]-_rngy[0])}\n        });\n    };\n    /**\n     * 滑动到指定位置\n     * \n     * @protected\n     * @method module:util/slider/slider._$$Slider#__onSlideToPosition\n     * @param  {Event} 事件对象\n     * @return {Void}\n     */\n    _pro.__onSlideToPosition = function(_event){\n        var _offset = _e._$offset(this.__dopt.view),\n            _pointer = {\n                x:_v._$clientX(_event),\n                y:_v._$clientY(_event)\n            };\n        this.__dragger._$setPosition({\n            top:_pointer.y-_offset.y,\n            left:_pointer.x-_offset.x\n        });\n    };\n    /**\n     * 设置滑块可移动范围\n     * \n     * 脚本举例\n     * ```javascript\n     *   // 设置可移动范围，单位px\n     *   _slider._$setRange({x:[0,99],y:[0,10]});\n     * ```\n     * @method module:util/slider/slider._$$Slider#_$setRange\n     * @param  {Object} arg0 - 可移动范围，不传则根据轨道自动计算\n     * @return {Void}\n     */\n    _pro._$setRange = function(_range){\n        // save current rate\n        var _rate;\n        if (!!this.__range){\n            var _position = this.__dragger._$getPosition();\n            _rate = {\n                x:_position.left/this.__range.x[1],\n                y:_position.top/this.__range.y[1]\n            };\n        }\n        // reset range\n        _range = _range||_o;\n        var _mx = (_range.x||_r)[1]||\n                  (this.__dopt.view.clientWidth-\n                   this.__dopt.body.offsetWidth),\n            _my = (_range.y||_r)[1]||\n                  (this.__dopt.view.clientHeight-\n                   this.__dopt.body.offsetHeight);\n        this.__range = {\n            x:_range.x||[0,_mx],\n            y:_range.y||[0,_my]\n        };\n        // adjust position\n        if (!!_rate) this._$setPosition(_rate);\n    };\n    /**\n     * 设置滑动比例\n     * \n     * 脚本举例\n     * ```javascript\n     *   // 设置滑动到此位置，按比例算\n     *   _slider._$setPosition({x:0.4,y:0.5});\n     * ```\n     * @method module:util/slider/slider._$$Slider#_$setPosition\n     * @param  {Object} arg0 - 滑动比例，范围[0,1]，格式如{x:0.4,y:0.5}\n     * @return {Void}\n     */\n    _pro._$setPosition = function(_rate){\n        _rate = _rate||_o;\n        this.__dragger._$setPosition({\n            top:this.__range.y[1]*(_rate.y||0),\n            left:this.__range.x[1]*(_rate.x||0)\n        });\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/slider/slider.simple.js",
    "content": "// link to util/slider/simple for compatible\n// use util/slider/simple for new project\nNEJ.define(['./simple.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/slider/slider.x.js",
    "content": "// link to util/slider/x for compatible\n// use util/slider/x for new project\nNEJ.define(['./x.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/slider/slider.xy.js",
    "content": "// link to util/slider/xy for compatible\n// use util/slider/xy for new project\nNEJ.define(['./xy.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/slider/slider.y.js",
    "content": "// link to util/slider/y for compatible\n// use util/slider/y for new project\nNEJ.define(['./y.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/slider/test/slider.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>slider测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n        <style type=\"text/css\">\n        \t#slide{position:absolute;top:0;height:20px;line-height:20px;width:20px;background:green;}\n\t\t\t#track{position:relative;height:20px;line-height:20px;width:100%;background:pink;}\n\t\t\t#slide1{position:absolute;top:0;height:20px;line-height:20px;width:20px;background:green;}\n            #track1{position:relative;height:200px;line-height:20px;width:20px;background:pink;}\n\t\t\t#slide2{position:absolute;top:0;height:20px;line-height:20px;width:20px;background:green;}\n            #track2{position:relative;height:200px;line-height:20px;width:100%;background:pink;}\n        </style>\n\t</head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit slider test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n\t\t<div id=\"track\"><div id=\"slide\"></div></div>\n\t\t<br />\n\t\t<div id=\"track1\"><div id=\"slide1\"></div></div>\n\t\t<br />\n\t\t<div id=\"track2\"><div id=\"slide2\"></div></div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./slider.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/slider/test/slider.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"slider\");\n\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v'),\n        _p = _('nej.ut');\n\n    test('sliderX',function(){\n        expect(0);\n\t\tvar _sd = _p._$$SliderX._$allocate({\n\t\t\trange:{x:[0,10]},\n\t\t\tslide:'slide',\n\t\t\ttrack:'track',\n\t\t\tonchange:function(_obj){\n\t\t\t\t_e._$style(_e._$get('slide'),{left:_obj.x.value});\n\t\t\t}\n\t\t});\n    });\n\n\ttest('sliderY',function(){\n        expect(0);\n        var _sd = _p._$$SliderY._$allocate({\n            range:{y:[0,10]},\n            slide:'slide1',\n            track:'track1',\n            onchange:function(_obj){\n                // _e._$style(_e._$get('slide'),{'top':_obj.y.value});\n            }\n        });\n    });\n\n\ttest('sliderXY',function(){\n        expect(0);\n        var _sd = _p._$$SliderXY._$allocate({\n            range:{x:[0,10],y:[0,10]},\n            slide:'slide2',\n            track:'track2',\n            onchange:function(_obj){\n                _e._$style(_e._$get('slide'),{left:_obj.x.value});\n            }\n        });\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}slider.test.js',\n    ['{lib}util/slider/slider.x.js',\n     '{lib}util/slider/slider.y.js',\n     '{lib}util/slider/slider.xy.js'],f);\n});\n"
  },
  {
    "path": "src/util/slider/test/sorter.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"sorter\");\n    var p = NEJ.P('nej.ut'),\n\t    e = NEJ.P('nej.e'),\n        u = NEJ.P('nej.u');\n    \n    //开始单元测试\n    test('生成排序控件', function() {\n        expect(0);\n        stop();\n        var _selector = p._$$MultiSelector._$allocate({\n            parent:'selector'\n        });\n        var _sorter = p._$$Sorter._$allocate({\n            selector:_selector,\n            holder:'holder',\n            mover:'mover',\n\t\t\tonbeforesort:function(_options){\n\t\t\t},\n\t\t\tonaftersort:function(_options){\n                var _list = _options.list,\n                    _p    = e._$get('selector');\n                // 刷新父亲节点\n                _p.innerHTML = '';\n                u._$forEach(_list,function(_item){\n                    _p.appendChild(_item);\n                });\n\t\t\t},\n\t\t\tonsort:function(_options){\n\t\t\t}\n        });\n        start();\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}sorter.test.js',\n    ['{lib}util/selector/selector.js','{lib}util/sorter/sorter.js'],f);\n});\n"
  },
  {
    "path": "src/util/slider/x.js",
    "content": "/*\n * ------------------------------------------\n * 水平滑动器逻辑封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/slider/x */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    './slider.js'\n],function(NEJ,_k,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 水平滑动器逻辑封装\n     *\n     * 样式举例\n     * ```css\n     * #slide{position:absolute;top:0;height:20px;line-height:20px;width:20px;background:green;}\n     * #track{position:relative;height:20px;line-height:20px;width:100%;background:pink;}\n     * ```\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"track\">\n     *   <div id=\"slide\"></div>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/slider/x'\n     * ],function(_t){\n     *     var _slider = _t._$$SliderX._$allocate({\n     *         range:{x:[0,100]},\n     *         slide:'slide',\n     *         track:'track',\n     *         onchange:function(_event){\n     *             _e._$style('slide',{\n     *                 left:_event.x.value+'px'\n     *             });\n     *         }\n     *     });\n     * });\n     * ```\n     * @class    module:util/slider/x._$$SliderX\n     * @extends  module:util/slider/slider._$$Slider\n     * @param    {Object}      config - 可选配置参数\n     * @property {Object}      range  - 滑动范围，默认为滑块可运动范围，如{x:[0,100],y:[0,1000]}\n     * @property {String|Node} thumb  - 滑块节点\n     * @property {String|Node} track  - 滑动轨道节点\n     */\n    _p._$$SliderX = _k._$klass();\n    _pro = _p._$$SliderX._$extend(_t._$$Slider);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/slider/x._$$SliderX#__reset\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        _options.direction = 1;\n        this.__super(_options);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/slider/xy.js",
    "content": "/*\n * ------------------------------------------\n * 水平垂直滑动器逻辑封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/slider/xy */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    './slider.js'\n],function(NEJ,_k,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 水平垂直滑动器逻辑封装\n     *\n     * 样式举例\n     * ```css\n     * #slide{position:absolute;top:0;height:20px;line-height:20px;width:20px;background:green;}\n     * #track{position:relative;height:500px;width:100%;background:pink;}\n     * ```\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"track\">\n     *   <div id=\"slide\"></div>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/slider/xy'\n     * ],function(_t){\n     *     var _slider = _t._$$SliderXY._$allocate({\n     *         range:{x:[0,100],y:[0,500]},\n     *         slide:'slide',\n     *         track:'track',\n     *         onchange:function(_event){\n     *             _e._$style('slide',{\n     *                 top:_event.y.value+'px',\n     *                 left:_event.x.value+'px'\n     *             });\n     *         }\n     *     });\n     * });\n     * ```\n     * @class    module:util/slider/xy._$$SliderXY\n     * @extends  module:util/slider/slider._$$Slider\n     * @param    {Object}      config - 轨可选配置参数\n     * @property {Object}      range  - 滑动范围，默认为滑块可运动范围，如{x:[0,100],y:[0,1000]}\n     * @property {String|Node} thumb  - 滑块节点\n     * @property {String|Node} track  - 滑动道节点\n     */\n    _p._$$SliderXY = _k._$klass();\n    _pro = _p._$$SliderXY._$extend(_t._$$Slider);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/slider/xy._$$SliderXY#__reset\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        _options.direction = 0;\n        this.__super(_options);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/slider/y.js",
    "content": "/*\n * ------------------------------------------\n * 垂直滑动器逻辑封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/slider/y */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    './slider.js'\n],function(NEJ,_k,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 垂直滑动器逻辑封装\n     *\n     * 样式举例\n     * ```css\n     * #slide{position:absolute;top:0;height:20px;line-height:20px;width:20px;background:green;}\n     * #track{position:relative;width:20px;height:500px;background:pink;}\n     * ```\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"track\">\n     *   <div id=\"slide\"></div>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/slider/y'\n     * ],function(_t){\n     *     var _slider = _t._$$SliderY._$allocate({\n     *         range:{y:[0,100]},\n     *         slide:'slide',\n     *         track:'track',\n     *         onchange:function(_event){\n     *             _e._$style('slide',{\n     *                 top:_event.y.value+'px'\n     *             });\n     *         }\n     *     });\n     * });\n     * ```\n     * @class    module:util/slider/y._$$SliderY\n     * @extends  module:util/slider/slider._$$Slider\n     * @param    {Object}      config - 可选配置参数\n     * @property {Object}      range  - 滑动范围，默认为滑块可运动范围，如{x:[0,100],y:[0,1000]}\n     * @property {String|Node} thumb  - 滑块节点\n     * @property {String|Node} track  - 滑动轨道节点\n     */\n    _p._$$SliderY = _k._$klass();\n    _pro = _p._$$SliderY._$extend(_t._$$Slider);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/slider/y._$$SliderY#__reset\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        _options.direction = 2;\n        this.__super(_options);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});"
  },
  {
    "path": "src/util/sort/demo/horizontal.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - 水平排序控件</title>\n    <meta charset=\"utf-8\" />\n    <style>\n      .box{position:relative;width:560px;margin:50px;padding:5px;overflow:hidden;background:#FFFF00;}\n      .box .it{float:left;width:100px;height:100px;line-height:100px;margin:5px;background:#fdc;border:1px solid #aaa;text-align:center;cursor:move;}\n      .box .j-selected{background:#00BB00;}\n      .box .holder{position:absolute;top:0;left:0;width:12px;background:#0000FF;overflow:hidden;}\n    </style>\n    <script>\n        function log(m){\n            var p = document.createElement('p');\n            p.innerHTML = m;\n            document.body.appendChild(p);\n        }\n    </script>\n  </head>\n  <body>\n      <div class=\"box\" id=\"abc\">\n        <div class=\"it\" data-value=\"1\">1</div>\n        <div class=\"it\" data-value=\"2\">2</div>\n        <div class=\"it\" data-value=\"3\">3</div>\n        <div class=\"it\" data-value=\"4\">4</div>\n        <div class=\"it\" data-value=\"5\">5</div>\n        <div class=\"it\" data-value=\"6\">6</div>\n        <div class=\"it\" data-value=\"7\">7</div>\n        <div class=\"it\" data-value=\"8\">8</div>\n        <div class=\"it\" data-value=\"9\">9</div>\n        <div class=\"it\" data-value=\"a\">a</div>\n      </div>\n      <p><input type=\"button\" value=\"result\" id=\"a\"/></p>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n      NEJ.define([\n          'base/event',\n          'base/element',\n          '../horizontal.js'\n      ],function(_v,_e,_t){\n          var _sorter = _t._$$HSortable._$allocate({\n              clazz:'it',\n              parent:'abc',\n              delta:50,\n              placeholder:_e._$create('div','holder')\n          });\n          \n          _v._$addEvent(\n              'a','click',function(){\n                  log(_sorter._$getSortList().join(','));\n              }\n          );\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/sort/demo/horizontal.trigger.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - 水平排序控件</title>\n    <meta charset=\"utf-8\" />\n    <style>\n      .box{position:relative;width:560px;margin:50px;padding:5px;overflow:hidden;background:#FFFF00;}\n      .box .it{position:relative;float:left;width:100px;height:100px;line-height:100px;margin:5px;background:#fdc;border:1px solid #aaa;text-align:center;}\n      .box .it .trg{position:absolute;top:0;left:0;width:100%;height:20px;line-height:20px;background:#008000;cursor:move;}\n      .box .j-selected{background:#00BB00;}\n      .box .holder{position:absolute;top:0;left:0;width:12px;background:#0000FF;overflow:hidden;}\n    </style>\n    <script>\n        function log(m){\n            var p = document.createElement('p');\n            p.innerHTML = m;\n            document.body.appendChild(p);\n        }\n    </script>\n  </head>\n  <body>\n      <div class=\"box\" id=\"abc\">\n        <div class=\"it\" data-value=\"1\"><span class=\"trg j-it\">&nbsp;</span>1</div>\n        <div class=\"it\" data-value=\"2\"><span class=\"trg j-it\">&nbsp;</span>2</div>\n        <div class=\"it\" data-value=\"3\"><span class=\"trg j-it\">&nbsp;</span>3</div>\n        <div class=\"it\" data-value=\"4\"><span class=\"trg j-it\">&nbsp;</span>4</div>\n        <div class=\"it\" data-value=\"5\"><span class=\"trg j-it\">&nbsp;</span>5</div>\n        <div class=\"it\" data-value=\"6\"><span class=\"trg j-it\">&nbsp;</span>6</div>\n        <div class=\"it\" data-value=\"7\"><span class=\"trg j-it\">&nbsp;</span>7</div>\n        <div class=\"it\" data-value=\"8\"><span class=\"trg j-it\">&nbsp;</span>8</div>\n        <div class=\"it\" data-value=\"9\"><span class=\"trg j-it\">&nbsp;</span>9</div>\n        <div class=\"it\" data-value=\"10\"><span class=\"trg j-it\">&nbsp;</span>10</div>\n        <div class=\"it\" data-value=\"11\"><span class=\"trg j-it\">&nbsp;</span>11</div>\n        <div class=\"it\" data-value=\"12\"><span class=\"trg j-it\">&nbsp;</span>12</div>\n      </div>\n      <p><input type=\"button\" value=\"result\" id=\"a\"/></p>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n      NEJ.define([\n          'base/event',\n          'base/element',\n          '../horizontal.js'\n      ],function(_v,_e,_t){\n          var _sorter = _t._$$HSortable._$allocate({\n              parent:'abc',\n              clazz:'it',\n              trigger:'j-it',\n              placeholder:_e._$create('div','holder')\n          });\n          \n          _v._$addEvent(\n              'a','click',function(){\n                  log(_sorter._$getSortList().join(','));\n              }\n          );\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/sort/demo/vertical.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - 垂直排序控件</title>\n    <meta charset=\"utf-8\" />\n    <style>\n      .box{position:relative;width:500px;margin:50px;padding:5px;overflow:hidden;background:#FFFF00;}\n      .box .it{height:50px;line-height:50px;margin:10px 0;background:#fdc;border:1px solid #aaa;text-align:center;cursor:move;}\n      .box .j-selected{background:#00BB00;}\n      .box .holder{position:absolute;top:0;left:0;height:12px;background:#0000FF;overflow:hidden;}\n    </style>\n    <script>\n        function log(m){\n            var p = document.createElement('p');\n            p.innerHTML = m;\n            document.body.appendChild(p);\n        }\n    </script>\n  </head>\n  <body>\n      \n      <div class=\"box\" id=\"abc\">\n        <div class=\"it\" data-value=\"1\">1</div>\n        <div class=\"it\" data-value=\"2\">2</div>\n        <div class=\"it\" data-value=\"3\">3</div>\n        <div class=\"it\" data-value=\"4\">4</div>\n        <div class=\"it\" data-value=\"5\">5</div>\n        <div class=\"it\" data-value=\"6\">6</div>\n        <div class=\"it\" data-value=\"7\">7</div>\n        <div class=\"it\" data-value=\"8\">8</div>\n        <div class=\"it\" data-value=\"9\">9</div>\n        <div class=\"it\" data-value=\"a\">a</div>\n      </div>\n      <p><input type=\"button\" value=\"result\" id=\"a\"/></p>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n      NEJ.define([\n          'base/event',\n          'base/element',\n          '../vertical.js'\n      ],function(_v,_e,_t){\n          var _sorter = _t._$$VSortable._$allocate({\n              clazz:'it',\n              parent:'abc',\n              placeholder:_e._$create('div','holder')\n          });\n          \n          _v._$addEvent(\n              'a','click',function(){\n                  log(_sorter._$getSortList().join(','));\n              }\n          );\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/sort/demo/vertical.trigger.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - 垂直排序控件</title>\n    <meta charset=\"utf-8\" />\n    <style>\n      .box{position:relative;width:500px;margin:50px;padding:5px;overflow:hidden;background:#FFFF00;}\n      .box .it{position:relative;height:50px;line-height:50px;margin:10px 0;background:#fdc;border:1px solid #aaa;text-align:center;}\n      .box .mv{position:absolute;top:0;right:0;width:30px;height:50px;background:#008000;cursor:move;}\n      .box .j-selected{background:#00BB00;}\n      .box .holder{position:absolute;top:0;left:0;height:12px;background:#0000FF;overflow:hidden;}\n    </style>\n    <script>\n        function log(m){\n            var p = document.createElement('p');\n            p.innerHTML = m;\n            document.body.appendChild(p);\n        }\n    </script>\n  </head>\n  <body>\n      \n      <div class=\"box\" id=\"abc\">\n        <div class=\"it\" data-value=\"1\"><span class=\"mv\">&nbsp;</span>1</div>\n        <div class=\"it\" data-value=\"2\"><span class=\"mv\">&nbsp;</span>2</div>\n        <div class=\"it\" data-value=\"3\"><span class=\"mv\">&nbsp;</span>3</div>\n        <div class=\"it\" data-value=\"4\"><span class=\"mv\">&nbsp;</span>4</div>\n        <div class=\"it\" data-value=\"5\"><span class=\"mv\">&nbsp;</span>5</div>\n        <div class=\"it\" data-value=\"6\"><span class=\"mv\">&nbsp;</span>6</div>\n        <div class=\"it\" data-value=\"7\"><span class=\"mv\">&nbsp;</span>7</div>\n        <div class=\"it\" data-value=\"8\"><span class=\"mv\">&nbsp;</span>8</div>\n        <div class=\"it\" data-value=\"9\"><span class=\"mv\">&nbsp;</span>9</div>\n        <div class=\"it\" data-value=\"a\"><span class=\"mv\">&nbsp;</span>a</div>\n      </div>\n      <p><input type=\"button\" value=\"result\" id=\"a\"/></p>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n      NEJ.define([\n          'base/event',\n          'base/element',\n          '../vertical.js'\n      ],function(_v,_e,_t){\n          var _sorter = _t._$$VSortable._$allocate({\n              clazz:'it',\n              parent:'abc',\n              trigger:'mv',\n              placeholder:_e._$create('div','holder')\n          });\n          \n          _v._$addEvent(\n              'a','click',function(){\n                  log(_sorter._$getSortList().join(','));\n              }\n          );\n      });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/sort/horizontal.js",
    "content": "/*\n * ------------------------------------------\n * 水平排序功能封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/sort/horizontal */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    './sortable.js'\n],function(NEJ,_k,_t,_p,_o,_f,_r,_pro){\n    /**\n     * 水平排序功能封装\n     * \n     * 样式举例\n     * ```css\n     *  .box{position:relative;width:560px;margin:50px;padding:5px;overflow:hidden;background:#FFFF00;}\n     *  .box .it{float:left;width:100px;height:100px;line-height:100px;margin:5px;background:#fdc;border:1px solid #aaa;text-align:center;cursor:move;}\n     *  .box .j-selected{background:#00BB00;}\n     *  .box .holder{position:absolute;top:0;left:0;width:12px;background:#0000FF;overflow:hidden;}\n     * ```\n     * \n     * 结构举例\n     * ```html\n     *  <div class=\"box\" id=\"abc\">\n     *    <div class=\"it\" data-value=\"1\">1</div>\n     *    <div class=\"it\" data-value=\"2\">2</div>\n     *    <div class=\"it\" data-value=\"3\">3</div>\n     *    <div class=\"it\" data-value=\"4\">4</div>\n     *    <div class=\"it\" data-value=\"5\">5</div>\n     *    <div class=\"it\" data-value=\"6\">6</div>\n     *    <div class=\"it\" data-value=\"7\">7</div>\n     *    <div class=\"it\" data-value=\"8\">8</div>\n     *    <div class=\"it\" data-value=\"9\">9</div>\n     *    <div class=\"it\" data-value=\"a\">a</div>\n     *    <div class=\"holder\" id=\"def\">&nbsp;</div>\n     *  </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     *  NEJ.define([\n     *      '../horizontal.js'\n     *  ],function(_t){\n     *      _t._$$HSortable._$allocate({\n     *          clazz:'it',\n     *          parent:'abc',\n     *          placeholder:'def'\n     *      });\n     *  });\n     * ```\n     * \n     * @class   module:util/sort/horizontal._$$HSortable\n     * @extends module:util/sort/sortable._$$Sortable\n     * \n     * @param  {Object} conifg - 可选配置参数\n     */\n    _p._$$HSortable = _k._$klass();\n    _pro = _p._$$HSortable._$extend(_t._$$Sortable);\n    /**\n     * 判断是否可以开始拖拽行为\n     *\n     * @abstract\n     * @method module:util/sort/sortable._$$HSortable#__canStartSort\n     * @param  {Object} arg0 - 初始鼠标位置\n     * @param  {Object} arg1 - 当前鼠标位置\n     * @return {Boolean}       是否可以开始拖拽\n     */\n    _pro.__canStartSort = function(_pos1,_pos2){\n        return Math.abs(_pos2.x-_pos1.x)>this.__delta;\n    };\n    /**\n     * 计算占位符位置信息\n     * \n     * @abstract\n     * @method module:util/sort/horizontal._$$HSortable#__doCalPlaceHolder\n     * @param  {Object} arg0 - 当前节点\n     * @param  {Object} arg1 - 鼠标位置\n     * @return {Object}        占位符信息\n     */\n    _pro.__doCalPlaceHolder = function(_box,_pointer){\n        var _isleft = _pointer.left<_box.width/2;\n        return {\n            top:_box.top,\n            height:_box.height,\n            left:_isleft?(_box.left-this.__holder.offsetWidth):(_box.left+_box.width),\n            position:_isleft?'beforeBegin':'afterEnd',\n            method:_isleft?'unshift':'pop'\n        };\n    };\n    \n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/sort/sortable.js",
    "content": "/*\n * ------------------------------------------\n * 排序功能封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/sort/sortable */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/event',\n    'base/element',\n    'base/util',\n    'util/event',\n    'util/scroll/smart'\n],function(NEJ,_k,_v,_e,_u,_t,_x,_p,_o,_f,_r,_pro){\n    /**\n     * 排序功能封装\n     * \n     * @class   module:util/sort/sortable._$$Sortable\n     * @extends module:util/event._$$EventTarget\n     * \n     * @param    {Object} conifg      - 可选配置参数\n     * @property {Node}   parent      - 容器节点\n     * @property {Node}   viewport    - 滚动条所在容器，拖拽超出此容器自动滚动\n     * @property {String} clazz       - 可排序节点的类标识，默认为j-sortable\n     * @property {String} trigger     - 触发排序节点的类标识，默认为clazz标识的节点\n     * @property {Node}   placeholder - 占位符，用于标识插入位置\n     * @property {Node}   thumbnail   - 移动缩略图，跟随鼠标移动\n     * @property {String} selected    - 排序节点选中样式，默认为j-selected\n     * @property {Number} delta       - 开始拖拽识别偏移量\n     */\n    /** \n     * 排序之前触发事件\n     * \n     * @event    module:util/sort/sortable._$$Sortable#onbeforesort\n     * @param    {Object}  event - 事件信息\n     * @property {Varable} value - 选中的排序节点或者节点列表\n     */\n    /** \n     * 排序变化触发事件\n     * \n     * @event module:util/sort/sortable._$$Sortable#onsortchange\n     * @param {Object} event - 事件信息\n     */\n    /** \n     * 排序缩略图更新事件 \n     * \n     * @event    module:util/sort/sortable._$$Sortable#onthumbupdate\n     * @param    {Object}     event   - 事件信息\n     * @property {Varable}    state   - 状态值，1-开始排序，2-排序中，3-排序结束\n     * @property {Number}     top     - 鼠标距页面顶部位置\n     * @property {Number}     left    - 鼠标距页面左侧位置\n     * @property {Node}       target  - 缩略图节点\n     * @property {Node|Array} source  - 排序节点或者节点列表\n     * @property {Boolean}    stopped - 是否阻止后续逻辑\n     */\n    /** \n     * 排序占位符更新事件\n     * \n     * @event    module:util/sort/sortable._$$Sortable#onholderupdate\n     * @param    {Object}     event    - 事件信息\n     * @property {Number}     top      - 鼠标相对于容器顶部偏移量\n     * @property {Number}     left     - 鼠标相对于容器左侧偏移量\n     * @property {Number}     width    - 排序节点宽度\n     * @property {Number}     height   - 排序节点高度\n     * @property {String}     position - 占位符插入位置，beforeBegin/afterEnd\n     * @property {Node}       target   - 占位符节点\n     * @property {Node|Array} source   - 排序节点或者节点列表\n     * @property {Node}       ref      - 插入点参考节点\n     * @property {Boolean}    stopped  - 是否阻止后续逻辑\n     */\n    _p._$$Sortable = _k._$klass();\n    _pro = _p._$$Sortable._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/sort/sortable._$$Sortable#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__clazz  = _options.clazz||'j-sortable';\n        this.__trigger = _options.trigger||this.__clazz;\n        this.__selected = _options.selected||'j-selected';\n        this.__viewport = _e._$get(_options.viewport);\n        this.__parent = _e._$get(_options.parent);\n        this.__holder = _e._$get(_options.placeholder);\n        this.__thumb  = _e._$get(_options.thumbnail);\n        this.__delta  = parseInt(_options.delta)||0;\n        _e._$removeByEC(this.__thumb);\n        _e._$removeByEC(this.__holder);\n        this.__doInitDomEvent([[\n            this.__parent,'mousedown',\n            this.__onSortStart._$bind(this)\n        ],[\n            document,'mousemove',\n            this.__onSorting._$bind(this)\n        ],[\n            document,'mouseup',\n            this.__onSortEnd._$bind(this)\n        ],[\n            this.__holder,'mousemove',\n            _v._$stop._$bind(_v)\n        ]]);\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/sort/sortable._$$Sortable#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        this.__doClearSort();\n    };\n    /**\n     * 取滚动条所在容器\n     * @return {Void}\n     */\n    _pro.__getScrollParent = function(){\n        var _parent = this.__parent;\n        if (_parent.scrollHeight>_parent.offsetHeight){\n            return _parent;\n        }\n        return _e._$getScrollViewPort(_parent);\n    };\n    /**\n     * 清除排序信息\n     * @return {Void}\n     */\n    _pro.__doClearSort = (function(){\n        var _unSelect = function(_node,_clazz){\n            if (!_u._$isArray(_node)){\n                _e._$delClassName(_node,_clazz);\n                return;\n            }\n            _u._$forEach(_node,function(_it){\n                _unSelect(_it,_clazz);\n            });\n        };\n        return function(){\n            this.__doUpdateThumb(3);\n            _e._$removeByEC(this.__holder);\n            _unSelect(this.__lsort,this.__selected);\n            if (!!this.__auto){\n                this.__auto._$recycle();\n                delete this.__auto;\n            }\n            delete this.__lsort;\n            delete this.__place;\n            delete this.__offset;\n            delete this.__pointer;\n        };\n    })();\n    /**\n     * 更新缩略图\n     * @return {Void}\n     */\n    _pro.__doUpdateThumb = function(_flag,_pointer){\n        if (!this.__thumb) return;\n        // check thumb update\n        _pointer = _pointer||_o;\n        var _event = {\n            // 1 - first, 2 - doing, 3 - end\n            state:_flag, \n            top:_pointer.y||0,\n            left:_pointer.x||0,\n            target:this.__thumb,\n            source:this.__lsort\n        };\n        if (_flag!=3){\n            document.body.appendChild(this.__thumb);\n        }\n        this._$dispatchEvent(\n            'onthumbupdate',_event\n        );\n        // sort end\n        if (_flag==3){\n            _e._$removeByEC(this.__thumb);\n            return;\n        }\n        // user updated\n        if (!!_event.stopped){\n            return;\n        }\n        // update position\n        _e._$style(\n            this.__thumb,{\n                top:_event.top+'px',\n                left:_event.left+'px'\n            }\n        );\n    };\n    /**\n     * 更新缩略图\n     * @return {Void}\n     */\n    _pro.__doUpdateHolder = (function(){\n        var _getOverBox = function(_from,_to){\n            var _offset = _e._$offset(_from,_to);\n            return {\n                top:_offset.y,\n                left:_offset.x,\n                width:_from.clientWidth,\n                height:_from.clientHeight\n            };\n        };\n        return function(_element,_pointer){\n            // calculate placeholder position\n            this.__parent.appendChild(this.__holder);\n            var _obox = _getOverBox(_element,this.__parent);\n            this.__place = this.__doCalPlaceHolder(\n                _obox,{\n                    top:_pointer.y-_obox.top-this.__offset.y,\n                    left:_pointer.x-_obox.left-this.__offset.x\n                }\n            );\n            this.__place.ref = _element; \n            this.__place.source = this.__lsort;\n            this.__place.target = this.__holder;\n            // check placeholder update\n            this._$dispatchEvent(\n                'onholderupdate',this.__place\n            );\n            if (!!this.__place.stopped){\n                return;\n            }\n            // update placeholder\n            _e._$style(\n                this.__holder,{\n                    top:this.__place.top+'px',\n                    left:this.__place.left+'px'\n                }\n            );\n            if (this.__place.width!=null){\n                _e._$setStyle(\n                    this.__holder,'width',\n                    this.__place.width+'px'\n                );\n            }\n            if (this.__place.height!=null){\n                _e._$setStyle(\n                    this.__holder,'height',\n                    this.__place.height+'px'\n                );\n            }\n        };\n    })();\n    /**\n     * 计算占位符位置信息\n     * \n     * @abstract\n     * @method module:util/sort/sortable._$$Sortable#__doCalPlaceHolder\n     * @param  {Object} arg0 - 当前节点\n     * @param  {Object} arg1 - 鼠标位置\n     * @return {Object}        占位符信息\n     */\n    _pro.__doCalPlaceHolder = _f;\n    /**\n     * 判断是否可以开始拖拽行为\n     *\n     * @abstract\n     * @method module:util/sort/sortable._$$Sortable#__canStartSort\n     * @param  {Object} arg0 - 初始鼠标位置\n     * @param  {Object} arg1 - 当前鼠标位置\n     * @return {Boolean}       是否可以开始拖拽\n     */\n    _pro.__canStartSort = _f;\n    /**\n     * 开始排序\n     * \n     * @protected\n     * @method module:util/sort/sortable._$$Sortable#__onSortStart\n     * @return {Void}\n     */\n    _pro.__onSortStart = function(_event){\n        // check sortable trigger element\n        var _element = _v._$getElement(\n            _event,'c:'+this.__trigger\n        );\n        if (!_element) return;\n        // void text selection\n        _v._$stop(_event);\n        // dump sort element\n        this.__lsort = _element;\n        if (!_e._$hasClassName(\n               _element,this.__clazz\n           )){\n            this.__lsort = _v._$getElement(\n                _event,'c:'+this.__clazz\n            );\n        }\n        // check before sort for multi-selection\n        try{\n            var _eobj = {\n                target:this.__lsort\n            };\n            this._$dispatchEvent(\n                'onbeforesort',_eobj\n            );\n            if (!!_eobj.value){\n                this.__lsort = \n                    _eobj.value||this.__lsort;\n            }\n        }catch(ex){\n            // ignore\n        }\n        // holder info\n        this.__offset = _e._$offset(this.__parent);\n        this.__pointer = {\n            x:_v._$clientX(_event),\n            y:_v._$clientY(_event)\n        };\n    };\n    /**\n     * 排序过程\n     * \n     * @protected\n     * @method module:util/sort/sortable._$$Sortable#__onSorting\n     * @return {Void}\n     */\n    _pro.__onSorting = function(_event){\n        if (!this.__lsort) return;\n        var _position = {\n            x:_v._$clientX(_event),\n            y:_v._$clientY(_event)\n        };\n        // check drag start\n        if (!this.__auto){\n            if (!this.__canStartSort(\n                    this.__pointer,_position\n                )){\n                return;\n            }\n            // update selected\n            var _isarr = _u._$isArray(this.__lsort);\n            if (!_isarr){\n                _e._$addClassName(\n                    this.__lsort,\n                    this.__selected\n                );\n            }\n            this.__doUpdateThumb(1,_position);\n            // for auto scroll\n            var _node = _isarr?this.__lsort[0]:this.__lsort;\n            this.__auto = _x._$$SmartScroll._$allocate({\n                viewport:this.__getScrollParent(),\n                step:_node.offsetHeight/5\n            });\n        }\n        // update thumbnail\n        this.__doUpdateThumb(2,_position);\n        var _element = _v._$getElement(\n            _event,'c:'+this.__clazz\n        );\n        if (!_element) return;\n        // single selection\n        if (_element==this.__lsort){\n            delete this.__place;\n            _e._$removeByEC(this.__holder);\n            return;\n        }\n        // update placeholder\n        this.__doUpdateHolder(\n            _element,{\n                x:_v._$pageX(_event),\n                y:_v._$pageY(_event)\n            }\n        );\n    };\n    /**\n     * 排序结束\n     * \n     * @protected\n     * @method module:util/sort/sortable._$$Sortable#__onSortEnd\n     * @return {Void}\n     */\n    _pro.__onSortEnd = (function(){\n        var _doUpdateSort = function(_list,_place){\n            if (!_place) return;\n            // sort single\n            if (!_u._$isArray(_list)){\n                _place.ref.insertAdjacentElement(\n                    _place.position,_list\n                );\n                return;\n            }\n            // sort multiple\n            var _it;\n            while(_it=_list[_place.method]()){\n                _place.ref.insertAdjacentElement(\n                    _place.position,_it\n                );\n            }\n        };\n        return function(_event){\n            if (!this.__lsort) return;\n            _doUpdateSort(\n                this.__lsort,\n                this.__place\n            );\n            this.__doClearSort();\n            this._$dispatchEvent('onsortchange');\n        };\n    })();\n    /**\n     * 取排序列表，如果节点带data-value属性则返回该属性值的列表，否则返回节点列表\n     * \n     * @method module:util/sort/sortable._$$Sortable#_$getSortList\n     * @return {Array} 排序列表\n     */\n    _pro._$getSortList = function(){\n        var _arr = [];\n        _u._$forEach(\n            _e._$getByClassName(\n                this.__parent,this.__clazz\n            ),function(_node){\n                _arr.push(_e._$dataset(_node,'value')||_node);\n            }\n        );\n        return _arr;\n    };\n    \n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/sort/vertical.js",
    "content": "/*\n * ------------------------------------------\n * 垂直排序功能封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/sort/vertical */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    './sortable.js'\n],function(NEJ,_k,_t,_p,_o,_f,_r,_pro){\n    /**\n     * 垂直排序功能封装\n     * \n     * 样式举例\n     * ```css\n     *  .box{position:relative;width:500px;margin:50px;padding:5px;overflow:hidden;background:#FFFF00;}\n     *  .box .it{height:50px;line-height:50px;margin:10px 0;background:#fdc;border:1px solid #aaa;text-align:center;cursor:move;}\n     *  .box .j-selected{background:#00BB00;}\n     *  .box .holder{position:absolute;top:0;left:0;height:12px;background:#0000FF;overflow:hidden;}\n     * ```\n     * \n     * 结构举例\n     * ```html\n     *  <div class=\"box\" id=\"abc\">\n     *    <div class=\"it\" data-value=\"1\">1</div>\n     *    <div class=\"it\" data-value=\"2\">2</div>\n     *    <div class=\"it\" data-value=\"3\">3</div>\n     *    <div class=\"it\" data-value=\"4\">4</div>\n     *    <div class=\"it\" data-value=\"5\">5</div>\n     *    <div class=\"it\" data-value=\"6\">6</div>\n     *    <div class=\"it\" data-value=\"7\">7</div>\n     *    <div class=\"it\" data-value=\"8\">8</div>\n     *    <div class=\"it\" data-value=\"9\">9</div>\n     *    <div class=\"it\" data-value=\"a\">a</div>\n     *    <div class=\"holder\" id=\"def\">&nbsp;</div>\n     *  </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     *  NEJ.define([\n     *      '../vertical.js'\n     *  ],function(_t){\n     *      var _sorter = _t._$$VSortable._$allocate({\n     *          clazz:'it',\n     *          parent:'abc',\n     *          placeholder:'def'\n     *      });\n     *  });\n     * ```\n     * \n     * @class   module:util/sort/vertical._$$VSortable\n     * @extends module:util/sort/sortable._$$Sortable\n     * \n     * @param  {Object} conifg - 可选配置参数\n     */\n    _p._$$VSortable = _k._$klass();\n    _pro = _p._$$VSortable._$extend(_t._$$Sortable);\n    /**\n     * 判断是否可以开始拖拽行为\n     *\n     * @abstract\n     * @method module:util/sort/sortable._$$VSortable#__canStartSort\n     * @param  {Object} arg0 - 初始鼠标位置\n     * @param  {Object} arg1 - 当前鼠标位置\n     * @return {Boolean}       是否可以开始拖拽\n     */\n    _pro.__canStartSort = function(_pos1,_pos2){\n        return Math.abs(_pos2.y-_pos1.y)>this.__delta;\n    };\n    /**\n     * 计算占位符位置信息\n     * \n     * @abstract\n     * @method module:util/sort/vertical._$$VSortable#__doCalPlaceHolder\n     * @param  {Object} arg0 - 当前节点\n     * @param  {Object} arg1 - 鼠标位置\n     * @return {Object}        占位符信息\n     */\n    _pro.__doCalPlaceHolder = function(_box,_pointer){\n        var _istop = _pointer.top<_box.height/2;\n        return {\n            left:_box.left,\n            width:_box.width,\n            top:_istop?(_box.top-this.__holder.offsetHeight):(_box.top+_box.height),\n            position:_istop?'beforeBegin':'afterEnd',\n            method:_istop?'unshift':'pop'\n        };\n    };\n    \n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/suggest/at.js",
    "content": "/*\n * ------------------------------------------\n * @提示控件封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/suggest/at */\nNEJ.define([\n    'base/klass',\n    'base/element',\n    'base/event',\n    'util/event',\n    'util/helper/select',\n    'util/cursor/cursor'\n],function(_k,_e,_v,_t,_t0,_t1,_p,_o,_f,_r,_pro){\n    /**\n     * AT提示控件\n     * \n     * 样式举例\n     * ```css\n     *  textarea{width:300px;height:200px;margin:0;padding:0;}\n     *  .tbox{position:relative;}\n     *  .tip{position:absolute;background:#fff;border:1px solid #aaa;}\n     *  .tip .it{height:20px;line-height:20px;}\n     *  .tip .it.js-selected{background:#1257F9;}\n     * ```\n     * \n     * 结构举例\n     * ```html\n     * <div class=\"tbox\" tabindex=\"10005\">\n     *   <textarea id=\"efg\"></textarea>\n     *   <div class=\"tip\" id=\"hij\"></div>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     *  NEJ.define([\n     *      'util/suggest/at'\n     *  ],function(_t){\n     *      _t._$$At._$allocate({\n     *          input:'efg',\n     *          tip:'hij',\n     *          onatchange:function(_event){\n     *              var _arr = [];\n     *              for(var i=9,v;i>=0;i--){\n     *                  v = _event.value+'-'+i;\n     *                  _arr.push('<div class=\"it\" data-value=\"'+v+'\">'+v+'</div>');\n     *              }\n     *              this._$update(_arr.join(''));\n     *          }\n     *      });\n     *  });\n     * ```\n     * \n     * @class    module:util/suggest/at._$$At\n     * @extends  module:util/event._$$EventTarget\n     * \n     * @param    {Object}        config   - 可选配置参数\n     * @property {Node|String}   input    - 输入节点\n     * @property {Node|String}   tip      - 提示列表节点\n     * @property {String|RegExp} keychar  - 触发提示的关键字符，默认为'@'\n     * @property {String}        selected - 提示选中样式\n     */\n    _p._$$At = _k._$klass();\n    _pro = _p._$$At._$extend(_t._$$EventTarget);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:util/suggest/at._$$At#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__sopt = {\n            loopable:!0,\n            onselect:this.__onSelect._$bind(this)\n        };\n        this.__super();\n    };\n    /**\n     * 控件重置\n     * \n     * @protected\n     * @method module:util/suggest/at._$$At#__reset\n     * @param  {Object} arg0 - 配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__keyword = _options.keychar||'@';\n        this.__input = _e._$get(_options.input);\n        this.__sopt.parent = _e._$get(_options.tip);\n        this.__sopt.selected = _options.selected||'js-selected';\n        // init event\n        this.__doInitDomEvent([[\n            this.__input,'input',\n            this.__onInput._$bind(this)\n        ],[\n            this.__input,'keydown',\n            this.__onKeyCheck._$bind(this)\n        ],[\n            this.__input,'mouseup',\n            this.__onInput._$bind(this)\n        ]]);\n        // init helper\n        this._$visibile(!1);\n    };\n    /**\n     * 控件销毁\n     * \n     * @protected\n     * @method module:util/suggest/at._$$At#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        if (!!this.__helper){\n            this.__helper._$recycle();\n            delete this.__helper;\n        }\n        delete this.__input;\n        delete this.__sopt.parent;\n    };\n    /**\n     * 更新提示控件位置\n     * @return {Void}\n     */\n    _pro.__doUpdateTipPosition = function(){\n        var _pos = _t1._$coordinate(this.__input);\n        _e._$style(\n            this.__sopt.parent,{\n                top:_pos.top+_pos.height+'px',\n                left:_pos.left+'px'\n            }\n        );\n    };\n    /**\n     * 输入变化事件\n     * \n     * @protected\n     * @method module:util/suggest/at._$$At#__onInput\n     * @param  {Event} 事件对象\n     * @return {Void}\n     */\n    _pro.__onInput = (function(){\n        var _reg0 = /[\\s\\b]/;\n        return function(_event){\n            var _pos = _t1._$cursor(this.__input),\n                _value = this.__input.value,\n                _arr = [];\n            for(var i=_pos.start,c;i>=0;i--){\n                c = _value.charAt(i);\n                if (_reg0.test(c)){\n                    break;\n                }\n                _arr.unshift(c);\n                if (c===this.__keyword){\n                    break;\n                }\n            }\n            // not find keyword\n            if (_arr[0]!=this.__keyword){\n                this._$update();\n                return;\n            }\n            // with keyword\n            _arr.shift();\n            this.__doUpdateTipPosition();\n            this._$dispatchEvent('onatchange',{\n                keyword:this.__keyword,\n                value:_arr.join('')\n            });\n        };\n    })();\n    /**\n     * 提示选中事件\n     * \n     * @protected\n     * @method module:util/suggest/at._$$At#__onSelect\n     * @param  {Event} 事件对象\n     * @return {Void}\n     */\n    _pro.__onSelect = function(_event){\n        var _value = _e._$dataset(_event.target,'value');\n        if (!!_value){\n            _value += ' ';\n            var _pos = _t1._$cursor(this.__input),\n                _str = this.__input.value,\n                _start = _pos.start;\n            for(;_start>=0;_start--){\n                if (_str.charAt(_start)==this.__keyword){\n                    break;\n                }\n            }\n            this.__input.value = _str.substr(0,_start+1)+\n                                 _value+_str.substr(_pos.end);\n            _t1._$cursor(this.__input,{\n                start:_start+_value.length+1\n            });\n        }\n        this._$update();\n    };\n    /**\n     * ESC键取消选择\n     * \n     * @protected\n     * @method module:util/suggest/at._$$At#__onKeyCheck\n     * @param  {Event} 事件对象@return {Void}\n     */\n    _pro.__onKeyCheck = function(_event){\n        if (_event.keyCode==27){\n            _v._$stop(_event);\n            this._$update();\n        }\n    };\n    /**\n     * 更新建议列表的可见性\n     * \n     * 脚本举例\n     * ```javascript\n     * // 设置选择列表可见\n     * _at._$visibile(true);\n     * // 设置选择列表不可见\n     * _at._$visibile(false);\n     * ```\n     *\n     * @method module:util/suggest/at._$$At#_$visibile\n     * @param  {Boolean} arg0 - 是否可见\n     * @return {Void}\n     */\n    _pro._$visibile = function(_visible){\n        _e._$setStyle(\n            this.__sopt.parent,'visibility',\n            !_visible ? 'hidden' : 'visible'\n        );\n        // reset select helper\n        if (!_visible&&!!this.__helper){\n            this.__helper = this.__helper._$recycle();\n        }\n        if(!!_visible&&!this.__helper){\n            this.__helper = _t0._$$SelectHelper._$allocate(this.__sopt);\n        }\n    };\n    /**\n     * 更新可选列表\n     * \n     * 脚本举例\n     * ```javascript\n     * // 更新选择列表内容\n     * var _arr = [];\n     * for(var i=0;i<10;i++){\n     *     _arr.push('<div>'+i+'</div>');\n     * }\n     * _at._$update(_arr.join(''));\n     * ```\n     * \n     * @method module:util/suggest/at._$$At#_$update\n     * @param  {String} arg0 - 列表HTML代码\n     * @return {Void}\n     */\n    _pro._$update = function(_html){\n        this.__sopt.parent.innerHTML = _html||'&nbsp;';\n        this._$visibile(!!_html);\n    };\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/suggest/demo/at.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - AT提示</title>\n    <meta charset=\"utf-8\" />\n    <style>\n      textarea{width:300px;height:200px;margin:0;padding:0;}\n      .txt{width:300px;height:30px;line-height:30px;}\n      .tbox{position:relative;zoom:1;outline:none;}\n      .tip{position:absolute;background:#fff;border:1px solid #aaa;}\n      .tip .it{height:20px;line-height:20px;}\n      .tip .it.js-selected{background:#1257F9;}\n    </style>\n  </head>\n  <body>\n    <div class=\"tbox\" tabindex=\"10005\">\n      <input class=\"txt\" type=\"text\" id=\"abc\"/>\n      <div class=\"tip\" id=\"def\"></div>\n    </div>\n    <p>aaaaaaaaaaaaa</p>\n    <p>aaaaaaaaaaaaa</p>\n    <p>aaaaaaaaaaaaa</p>\n    <p>aaaaaaaaaaaaa</p>\n    <p>aaaaaaaaaaaaa</p>\n    <p>aaaaaaaaaaaaa</p>\n    <p>aaaaaaaaaaaaa</p>\n    <p>aaaaaaaaaaaaa</p>\n    <p>aaaaaaaaaaaaa</p>\n    <p>aaaaaaaaaaaaa</p>\n    <div class=\"tbox\" tabindex=\"10006\">\n      <textarea id=\"efg\"></textarea>\n      <div class=\"tip\" id=\"hij\"></div>\n    </div>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            'base/element',\n            'util/suggest/at'\n        ],function(_e,_t){\n            var _onchange = function(_event){\n                var _arr = [];\n                for(var i=9,v;i>=0;i--){\n                    v = _event.value+'-'+i;\n                    _arr.push('<div class=\"it\" data-value=\"'+v+'\">'+v+'</div>');\n                }\n                this._$update(_arr.join(''));\n            };\n            _t._$$At._$allocate({\n                input:'abc',\n                tip:'def',\n                onatchange:_onchange\n            });\n            _t._$$At._$allocate({\n                input:'efg',\n                tip:'hij',\n                onatchange:_onchange\n            });\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/suggest/demo/suggest.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - 建议提示</title>\n    <meta charset=\"utf-8\" />\n    \n    <style>\n        .box{position:relative;text-align:left;}\n        .txt{width:300px;height:26px;line-height:26px;}\n        .crd{position:absolute;top:30px;left:0;width:300px;background:#aaa;border:1px solid #eee;}\n        .itm{height:20px;line-height:20px;}\n         .crd .js-selected{background:#ddd;}\n    </style>\n    \n  </head>\n  <body>\n    \n    <div class=\"box\">\n      <input type=\"text\" class=\"txt\" id=\"abc\"/>\n      <div class=\"crd\" id=\"efg\"></div>\n    </div>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            'util/suggest/suggest'\n        ],function(_t){\n            _t._$$Suggest._$allocate({\n                input:'abc',\n                body:'efg',\n                onchange:function(_value){\n                    var _arr = [];\n                    for(var i=0,v;i<10;i++){\n                        v = _value+i;\n                        _arr.push('<div data-value=\"'+v+'\">'+v+'</div>');\n                    }\n                    this._$update(_arr.join(''));\n                },\n                onselect:function(_value){\n                    console.log(_value);\n                }\n            });\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/suggest/suggest.js",
    "content": "/*\n * ------------------------------------------\n * 建议提示控件封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/suggest/suggest */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'util/event',\n    'util/helper/select'\n],function(NEJ,_k,_e,_t0,_t1,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 建议提示控件\n     *\n     * 样式举例\n     * ```css\n     * .box{position:relative;width:100px;}\n     * .xuanzhong{background:pink;}\n     * #suggest-input{height:24px;line-height:24px;}\n     * #card0{position:absolute;top:40px;left:0;width:100%;height:auto;background:#ccc;}\n     * ```\n     *\n     * 结构举例\n     * ```html\n     * <div class=\"box\" tabindex=\"10005\">\n     *   <input id=\"suggest-input\" type=\"text\" />\n     *   <div id=\"suggest-list\"></div>\n     * </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/suggest/suggest'\n     * ],function(_t){\n     *     var _suggest = _t._$$Suggest._$allocate({\n     *         input:'suggest-input',\n     *         body:'suggest-list',\n     *         selected:'xuanzhong',\n     *         onchange:function(_value){\n     *             var _arr = [];\n     *             for(var i = 1; i < 10;i++){\n     *                 // 选项中设置data-value来触发选项变化时自动同步到输入框中\n     *                 // 默认选中第一项，只需在第一项加选中样式即可\n     *                 _arr.push('<p '+(i==1?'xuanzhong':'')+' data-value=\"'+i+'\">'+i+'</p>');\n     *             }\n     *             // 输入框改变，改变select的列表内容\n     *             this._$update(_arr.join(''));\n     *         },\n     *         onselect:function(_value){\n     *             // 选择一个值的回调\n     *         }\n     *     });\n     * });\n     * ```\n     * @class    module:util/suggest/suggest._$$Suggest\n     * @extends  module:util/event._$$EventTarget\n     * @param    {Object}      config   - 可选配置参数\n     * @property {Node|String} input    - 输入框\n     * @property {Node|String} body     - 提示卡片节点\n     * @property {Boolean}     autofill - 选择时是否自动填充\n     * @property {Boolean}     noblur   - 禁用失去焦点时是否触发选中效果\n     * @property {String}      clazz    - 可选节点样式标识，默认为所有子节点\n     * @property {String}      selected - 提示项选中样式，默认为js-selected\n     */\n    /**\n     * 输入内容变化触发事件\n     * @event  module:util/suggest/suggest._$$Suggest#onchange\n     * @param  {String} event - 输入框去前后空格后的内容\n     */\n    /**\n     * 选中建议项触发事件\n     * @event  module:util/suggest/suggest._$$Suggest#onselect\n     * @param  {String} event - 节点的data-value值，没有则取节点的value\n     */\n    _p._$$Suggest = _k._$klass();\n    _pro = _p._$$Suggest._$extend(_t0._$$EventTarget);\n    /**\n     * 控件初始化\n     *\n     * @protected\n     * @method module:util/suggest/suggest._$$Suggest#__init\n     * @return {Void}\n     */\n    _pro.__init = function(){\n        this.__sopt = {\n            loopable:!0,\n            onselect:this.__onSelect._$bind(this),\n            onchange:this.__onSelectionChange._$bind(this)\n        };\n        this.__super();\n    };\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/suggest/suggest._$$Suggest#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        // init node\n        this.__auto  = !!_options.autofill;\n        this.__input = _e._$get(_options.input);\n        this.__sopt.clazz = _options.clazz;\n        this.__sopt.parent = _e._$get(_options.body);\n        this.__sopt.selected = _options.selected||'js-selected';\n        // init event\n        this.__doInitDomEvent([[\n            this.__input,'input',\n            this.__onInput._$bind(this)\n        ],[\n            this.__input,'focus',\n            this.__onInput._$bind(this)\n        ]]);\n        if (!_options.noblur){\n            this.__doInitDomEvent([[\n                this.__input,'blur',\n                this.__onBlur._$bind(this)\n            ]]);\n        }\n        // init helper\n        this._$visibile(!1);\n        this.__helper = _t1._$$SelectHelper._$allocate(this.__sopt);\n    };\n    /**\n     * 控件销毁\n     *\n     * @protected\n     * @method module:util/suggest/suggest._$$Suggest#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = function(){\n        this.__super();\n        if (!!this.__helper){\n            this.__helper._$recycle();\n            delete this.__helper;\n        }\n        delete this.__xxx;\n        delete this.__input;\n        delete this.__sopt.parent;\n    };\n    /**\n     * 输入框失去焦点事件\n     * @return {Void}\n     */\n    _pro.__onBlur = function(){\n        this.__onSelect({\n            target:this.__helper._$getSelectedNode()\n        });\n    };\n    /**\n     * 输入内容变化触发事件\n     *\n     * @protected\n     * @method module:util/suggest/suggest._$$Suggest#__onInput\n     * @return {Void}\n     */\n    _pro.__onInput = function(){\n        var _value = this.__input.value.trim();\n        if (!_value){\n            this._$visibile(!1);\n        }else if(!this.__xxx){\n            this._$dispatchEvent('onchange',_value);\n        }\n    };\n    /**\n     * 更新输入框内容\n     *\n     * @protected\n     * @method module:util/suggest/suggest._$$Suggest#__doUpdateValue\n     * @param  {Object} arg0 - 值信息\n     * @return {Void}\n     */\n    _pro.__doUpdateValue = function(_value){\n        // lock onchange for input value setting\n        if (!!this.__xxx){\n            return;\n        }\n        this.__xxx = !0;\n        if (!!_value&&_value!=this.__input.value){\n            this.__input.value = _value;\n        }\n        this.__xxx = !1;\n    };\n    /**\n     * 建议项选中事件\n     *\n     * @protected\n     * @method module:util/suggest/suggest._$$Suggest#__onSelect\n     * @param  {Object} arg0 - 事件信息\n     * @return {Void}\n     */\n    _pro.__onSelect = function(_event){\n        var _value = _e._$dataset(_event.target,'value')||'';\n        this.__doUpdateValue(_value);\n        _value = _value||this.__input.value;\n        this._$update('');\n        this._$dispatchEvent('onselect',_value,{\n            target:_event.target,\n            enter:_event.enter,\n            value:_value\n        });\n    };\n    /**\n     * 建议卡片选择变化事件\n     *\n     * @protected\n     * @method module:util/suggest/suggest._$$Suggest#__onSelectionChange\n     * @param  {Object} Object 事件信息\n     * @return {Void}\n     */\n    _pro.__onSelectionChange = function(_event){\n        if (this.__auto){\n            this.__doUpdateValue(\n                _e._$dataset(_event.target,'value')||''\n            );\n        }\n    };\n    /**\n     * 设置列表，用于切换列表选择卡片是否可见，不建议使用\n     *\n     * 脚本举例\n     * ```javascript\n     * // _list是节点列表\n     * _suggest._$setList(_list);\n     * ```\n     *\n     * @deprecated\n     * @method module:util/suggest/suggest._$$Suggest#_$setList\n     * @see    module:util/suggest/suggest._$$Suggest#_$visibile\n     * @param  {Array} arg0 - 建议项节点列表\n     * @return {Void}\n     */\n    _pro._$setList = function(_list){\n        this._$visibile(!!_list&&_list.length>0);\n    };\n    /**\n     * 更新建议列表的可见性\n     *\n     * 脚本举例\n     * ```javascript\n     * // 设置选择列表可见\n     * _suggest._$visibile(true);\n     * // 设置选择列表不可见\n     * _suggest._$visibile(false);\n     * ```\n     *\n     * @method module:util/suggest/suggest._$$Suggest#_$visibile\n     * @param  {Boolean} arg0 - 是否可见\n     * @return {Void}\n     */\n    _pro._$visibile = function(_visible){\n        var _visible = !_visible?'hidden':'visible';\n        this.__sopt.parent.style.visibility = _visible;\n        if (_visible==='hidden'){\n            this.__sopt.parent.innerHTML = '';\n        }\n    };\n    /**\n     * 更新可选列表\n     *\n     * 脚本举例\n     * ```javascript\n     * // 更新选择列表内容\n     * var _arr = [];\n     * for(var i=0;i<10;i++){\n     *     _arr.push('<div>'+i+'</div>');\n     * }\n     * _suggest._$update(_arr.join(''));\n     * ```\n     *\n     * @method module:util/suggest/suggest._$$Suggest#_$update\n     * @param  {String} arg0 - 列表HTML代码\n     * @return {Void}\n     */\n    _pro._$update = function(_html){\n        this.__sopt.parent.innerHTML = _html||'&nbsp;';\n        this._$visibile(!!_html);\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/suggest/test/suggest.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>suggest测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style type=\"text/css\">\n\t\t\t.box{position:relative;width:100px;}\n\t\t\t.xuanzhong{background:pink;}\n\t\t\t#suggest-input{height:24px;line-height:24px;padding:0;margin:0;border:solid 2px #ccc;}\n\t\t\t#card0{position:absolute;top:28px;left:0;width:100%;height:auto;background:#ccc;}\n\t\t</style>\n    </head>\n    <body onselectstart=\"return false\">\n        <h1 id=\"qunit-header\">Qunit suggest test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n\t\t<div class=\"box\">\n\t\t\t<input id=\"suggest-input\"  type=\"text\" />\n\t\t\t<div id=\"card0\"></div>\n\t\t</div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./suggest.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/suggest/test/suggest.test.js",
    "content": "var f = function(){\n    module(\"suggest\");\n\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v'),\n\t\t_p = _('nej.ut');\n    test('suggest',function(){\n\t\tstop();\n        expect(0);\n\t\tvar _ipt = _e._$get('suggest-input');\n\t\tvar _card0 = _e._$get('card0');\n\t\tvar _sg = _p._$$Suggest._$allocate({\n\t\t\tinput:_ipt,\n\t\t\tbody:'card0',\n\t\t\tselected:'xuanzhong',\n\t\t\tonchange:function(_value){\n\t\t\t\tvar _item = '';\n\t\t\t\tfor(var i = 1; i < 10;i++){\n\t\t\t\t    _item += '<p data-value='+i+'>'+i+'</p>';\n\t\t\t\t}\n\t\t\t\t_card0.innerHTML = _item;\n\t\t\t\t_sg._$setList(_e._$getChildren(_card0));\n\t\t\t},\n\t\t\tonselect:function(_value){\n\t\t\t\t// ok(true,'选择了一个值'+_value);\n\t\t\t\t// start();\n\t\t\t}\n\t\t});\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}suggest.test.js',['{lib}util/suggest/suggest.js'],f);\n});\n\n"
  },
  {
    "path": "src/util/tab/tab.js",
    "content": "/*\n * ------------------------------------------\n * 标签切换控件封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/tab/tab */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/event',\n    'base/util',\n    'base/element',\n    'util/event'\n],function(NEJ,_k,_v,_u,_e,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 标签切换控件封装\n     *\n     * 结构举例\n     *\n     * ```html\n     *   <div id=\"box\">\n     *       <a>1</a>\n     *       <a>2</a>\n     *       <a class=\"js-disabled\">3</a>\n     *       <a>4</a>\n     *   </div>\n     * ```\n     *\n     * 脚本举例\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'util/tab/tab'\n     * ],function(_t){\n     *     // 实例化控件\n     *     var _tab = _t._$$Tab._$allocate({\n     *         list:_e._$getChildren('box'),\n     *         index:1,\n     *         onchange:function(_event){\n     *             // TODO\n     *         }\n     *     });\n     *     // 使用控件\n     *     _tab._$go(2);\n     * });\n     * ```\n     *\n     * @class   module:util/tab/tab._$$Tab\n     * @extends module:util/event._$$EventTarget\n     *\n     * @param    {Object}  config   - 可选配置参数\n     * @property {Array}   list     - 标签项列表\n     * @property {Number}  index    - 初始选中项索引值，默认为0\n     * @property {String}  event    - 触发选择事件名称，默认为click\n     * @property {Boolean} inverse  - 是否反过程，true表示选中时删除选中样式，否则选中时添加样式\n     * @property {String}  disabled - 选项禁用样式，默认为js-disabled\n     * @property {String}  selected - 选中样式名，默认为js-selected\n     */\n    /**\n     * 标签切换事件，输入{last:1,index:5}\n     *\n     * ```javascript\n     * NEJ.define([\n     *     'util/tab/tab'\n     * ],function(_t){\n     *     // 实例化控件\n     *     var _tab = _t._$$Tab._$allocate({\n     *         list:_e._$getChildren(_e._$get('box')),\n     *         index:1,\n     *         onchange:function(_event){\n     *             // _event.last   上一次的tab索引\n     *             // _event.index  需要切换到的tab索引\n     *             // _event.list   节点列表\n     *             // _event.data   节点上通过data-value设置的内容\n     *             // TODO\n     *         }\n     *     });\n     * });\n     * ```\n     *\n     * @event    module:util/tab/tab._$$Tab#onchange\n     * @param    {Object}  event   - tab信息\n     * @property {Number}  last    - 上一次的tab索引\n     * @property {Number}  index   - 需要切换到的tab索引\n     * @property {Array}   list    - 节点列表\n     * @property {String}  data    - 节点上通过data-value设置的内容\n     * @property {Boolean} stopped - 是否阻止触发节点的默认事件，回调过程中如果设置为false则后续继续触发节点的默认事件\n     */\n    _p._$$Tab = _k._$klass();\n    _pro = _p._$$Tab._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/tab/tab._$$Tab#__reset\n     * @param  {Object} arg0 - 可选配置参数\n     * @return {Void}\n     */\n    _pro.__reset = function(_options){\n        this.__super(_options);\n        this.__name = _options.event||'click';\n        this.__selected = _options.selected||'js-selected';\n        this.__disabled = _options.disabled||'js-disabled';\n        this.__inversed = !!_options.inverse;\n        this.__doTabListCheck(_options.list);\n        this._$go(_options.index||0);\n    };\n    /**\n     * 控件回收\n     *\n     * @protected\n     * @method module:util/tab/tab._$$Tab#__destroy\n     * @return {Void}\n     */\n    _pro.__destroy = (function(){\n        var _doResetSelect = function(_node){\n            this.__doTabItemSelect(_node,!1);\n        };\n        return function(){\n            this.__super();\n            _u._$forEach(\n                this.__list,\n                _doResetSelect,this\n            );\n            delete this.__list;\n            delete this.__name;\n            delete this.__index;\n            delete this.__disabled;\n            delete this.__selected;\n            delete this.__inversed;\n       };\n    })();\n    /**\n     * 初始化标签列表\n     *\n     * @protected\n     * @method module:util/tab/tab._$$Tab#__doTabListCheck\n     * @param  {Array} arg0 - 标签节点列表\n     * @return {Void}\n     */\n    _pro.__doTabListCheck = (function(){\n        var _doInitDomEvent = function(_item){\n            if (!_item) return;\n            this.__list.push(_item);\n            var _index = this.__list.length-1,\n                _handler = this.__cblist[_index];\n            if (!_handler){\n                _handler = this._$go._$bind(this,_index);\n                this.__cblist[_index] = _handler;\n            }\n            this.__doInitDomEvent([[_item,this.__name,_handler]]);\n        };\n        return function(_list){\n            this.__list = [];\n            if (!this.__cblist) this.__cblist = [];\n            _u._$forEach(_list,_doInitDomEvent,this);\n        };\n    })();\n    /**\n     * 设置标签选中状态\n     *\n     * @protected\n     * @method module:util/tab/tab._$$Tab#__doTabItemSelect\n     * @param  {Node}    arg0 - 标签节点\n     * @param  {Boolean} arg1 - 是否选中\n     * @return {Void}\n     */\n    _pro.__doTabItemSelect = function(_element,_selected){\n        !!_selected&&!this.__inversed\n        ? _e._$addClassName(_element,this.__selected)\n        : _e._$delClassName(_element,this.__selected);\n    };\n    /**\n     * 切换到指定索引位置\n     *\n     * ```javascript\n     *   // 切换到索引为2的位置，如果当前索引为2则不触发回调\n     *   _tab._$go(2);\n     *   // 切换索引为2，如果当前索引为2也触发onchange回调\n     *   _tab._$go(2,true);\n     * ```\n     *\n     * @method module:util/tab/tab._$$Tab#_$go\n     * @param  {Number}  arg0 - 索引值\n     * @param  {Boolean} arg1 - 是否强行触发onchange事件\n     * @return {Void}\n     */\n    _pro._$go = function(_index,_force){\n        var _element = this.__list[_index];\n        if (_force!=!0&&(_index==this.__index||!_element||\n            _e._$hasClassName(_element,this.__disabled))){\n            _v._$stopDefault(arguments[1]);\n        }\n        var _event = {\n            stopped:!0,\n            index:_index,\n            last:this.__index,\n            list:this._$getList(),\n            data:_e._$dataset(_element,'value')\n        };\n        this.__index = _index;\n        _element = this.__list[_event.last];\n        if (!!_element){\n            this.__doTabItemSelect(_element,!1);\n        }\n        _element = this.__list[this.__index];\n        this.__doTabItemSelect(_element,!0);\n        this._$dispatchEvent('onchange',_event);\n        if (_event.stopped){\n            _v._$stopDefault(arguments[1]);\n        }\n    };\n    /**\n     * 取当前选中项索引\n     *\n     * ```javascript\n     *   // 获取当前选中的索引\n     *   var index = _tab._$getIndex();\n     * ```\n     *\n     * @method module:util/tab/tab._$$Tab#_$getIndex\n     * @return {Number} 当前选中项索引\n     */\n    _pro._$getIndex = function(){\n        return this.__index;\n    };\n    /**\n     * 取Tab控件关联的节点列表\n     *\n     * ```javascript\n     *   // 获取关联的节点列表\n     *   _tab._$getList();\n     * ```\n     *\n     * @method module:util/tab/tab._$$Tab#_$getList\n     * @return {Array} 关联的节点列表\n     */\n    _pro._$getList = function(){\n        return this.__list;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/tab/tab.view.js",
    "content": "// link to util/tab/view for compatible\n// use util/tab/view for new project\nNEJ.define(['./view.js'],function(_t){return _t;});\n"
  },
  {
    "path": "src/util/tab/test/tab.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>tab测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n\t\t<style type=\"text/css\">\n\t\t\t#box a{display:inline-block;margin:5px;cursor:pointer;}\n\t\t\t.js-selected{color:pink;}\n\t\t\t.js-disabled{color:red;}\n\t\t</style>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit tab test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n\t\t<div id=\"box\">\n\t\t\t<a>1</a>\n\t\t\t<a>2</a>\n\t\t\t<a class=\"js-disabled\">3</a>\n\t\t\t<a>4</a>\n\t\t</div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./tab.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/tab/test/tab.test.js",
    "content": "var f = function(){\n    module(\"tab\");\n\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v'),\n        _p = _('nej.ut');\n\n    test('tab',function(){\n        stop();\n\t\tvar _tb = _p._$$Tab._$allocate({\n\t\t\tlist:_e._$getChildren(_e._$get('box')),\n\t\t\tindex:1,\n\t\t\tonchange:function(_event){\n\t\t\t\tok(true,'上一次页面是:'+_event.last);\n\t\t\t\tok(true,'当前页面是:'+_event.index);\n\t\t\t\tstart();\n\t\t\t}\n\t\t});\n\t\t// _tb._$go(2);\n    });\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}tab.test.js',['{lib}util/tab/tab.js'],f);\n});\n\n"
  },
  {
    "path": "src/util/tab/view.js",
    "content": "/*\n * ------------------------------------------\n * 标签切换控件封装实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/tab/view */\nNEJ.define([\n    'base/global',\n    'base/klass',\n    'base/element',\n    'base/util',\n    'util/event'\n],function(NEJ,_k,_e,_u,_t,_p,_o,_f,_r){\n    var _pro;\n    /**\n     * 标签切换控件封装\n     * \n     * 结构举例\n     * ```html\n     * <div id=\"box\">\n     *   <a href=\"#\" data-abc=\"111\">1</a>\n     *   <a href=\"#\" data-abc=\"222\">2</a>\n     *   <a href=\"#\" data-abc=\"333\">3</a>\n     *   <a href=\"#\" data-abc=\"444\">4</a>\n     * </div>\n     * ```\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/tab/tab.view'\n     * ],function(_t){\n     *     // instance\n     *     var _tv = _t._$$TabView._$allocate({\n     *         dataset:'abc',\n     *         list:_e._$getChildren('box'),\n     *         oncheck:function(_event){\n     *             _event.matched = _event.target.indexOf(_event.source)>=0;\n     *         }\n     *     });\n     *     // check match\n     *     _tv._$match('333');\n     * });\n     * ```\n     * \n     * @class    module:util/tab/view._$$TabView\n     * @extends  module:util/event._$$EventTarget\n     * @param    {Object} config   - 可选配置参数\n     * @property {Array}  list     - 标签项列表\n     * @property {Number} dataset  - 属性名称，默认为id\n     * @property {String} selected - 选中样式名，默认为js-selected\n     */\n    /** \n     * 标签值验证事件\n     * \n     * @event    module:util/tab/view._$$TabView#oncheck\n     * @param    {Object}  event   - 事件信息\n     * @property {Number}  source  - 原始值\n     * @property {Number}  target  - 目标值\n     * @property {Boolean} matched - 是否匹配\n     */\n    _p._$$TabView = _k._$klass();\n    _pro = _p._$$TabView._$extend(_t._$$EventTarget);\n    /**\n     * 控件重置\n     *\n     * @protected\n     * @method module:util/tab/view._$$TabView#__reset\n     * @param  {Object} arg0 - 配置信息\n     * @return {Void}\n     */\n    _pro.__reset = (function(){\n        // check equal\n        var _doMatchEq = function(_event){\n            _event.matched = _event.source==_event.target;\n        };\n        return function(_options){\n            _options.oncheck = \n                _options.oncheck||_doMatchEq;\n            this.__super(_options);\n            this.__list = _options.list;\n            this.__name = _options.dataset||'id';\n            this.__selected = _options.selected||'js-selected';\n        };\n    })();\n    /**\n     * 验证匹配情况\n     *\n     * @method module:util/tab/view._$$TabView#_$match\n     * @param  {String} arg0 - 待匹配值\n     * @return {Node}          匹配的节点\n     */\n    _pro._$match = function(_value){\n        var _element,\n            _event = {target:_value};\n        _u._$forEach(\n            this.__list,\n            function(_node){\n                delete _event.matched;\n                _event.source = _e._$dataset(_node,this.__name);\n                this._$dispatchEvent('oncheck',_event);\n                if (!_event.matched){\n                    _e._$delClassName(_node,this.__selected);\n                }else{\n                    _element = _node;\n                    _e._$addClassName(_node,this.__selected);\n                }\n            },this\n        );\n        return _element;\n    };\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.ut'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/template/demo/a.css",
    "content": ".aa{color:#df3563;}"
  },
  {
    "path": "src/util/template/demo/a.html",
    "content": "<textarea placeholder=\"快速回复\" value=\"\"></textarea>"
  },
  {
    "path": "src/util/template/demo/a.js",
    "content": "console.log('textarea exline script')"
  },
  {
    "path": "src/util/template/demo/b.css",
    "content": ".bb{color:#00bb00;}"
  },
  {
    "path": "src/util/template/demo/b.html",
    "content": "<p>222222222</p>\n<p><br>44444455555555555</p>"
  },
  {
    "path": "src/util/template/demo/b.js",
    "content": "console.log('script exline script')"
  },
  {
    "path": "src/util/template/demo/jst.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n      <title>test template</title>\n      <meta charset=\"utf-8\" />\n  </head>\n  <body>\n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            '../jst.js',\n            'text!./b.html'\n        ],function(l,html){\n            var sn = l._$add(html);\n            console.log(l._$get(sn,{src:'http://a.b.com/',type:'abc'}));\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/template/demo/tpl.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n      <title>test template</title>\n      <meta charset=\"utf-8\" />\n  </head>\n  <body>\n    <p class=\"aa\">11111111111111111111<a class=\"a\">4444444</a></p>\n    <div id=\"xyz\">\n        <textarea name=\"css\" id=\"ta-css-0\">.a{color:#dcc}</textarea>\n        <textarea name=\"css\" data-src=\"./a.css\"></textarea>\n        <textarea name=\"js\" id=\"ta-js-0\">console.log('textarea inline script')</textarea>\n        <textarea name=\"js\" data-src=\"./a.js\"></textarea>\n        <textarea name=\"html\" data-src=\"./a.html\"></textarea>\n    </div>\n    <p class=\"bb\">22222222222222222<a class=\"b\">55555</a></p>\n    <div id=\"uvw\">\n        <script type=\"nej/css\" id=\"sc-css-0\">.b{color:#fdc}</script>\n        <script type=\"nej/css\" data-src=\"./b.css\"></script>\n        <script type=\"nej/js\" id=\"sc-js-0\">console.log('script inline script')</script>\n        <script type=\"nej/js\" data-src=\"./b.js\"></script>\n        <script type=\"html\" data-src=\"./b.html\"></script>\n    </div>\n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            '../tpl.js'\n        ],function(_l){\n            _l._$parseTemplate('xyz');\n            _l._$parseTemplate('uvw');\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/template/jst.js",
    "content": "/*\n * ------------------------------------------\n * JST模板二次封装文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module  util/template/jst */\nNEJ.define([\n    'base/global',\n    'base/util',\n    'base/element',\n    'base/chain',\n    'util/template/trimpath'\n],function(NEJ,_u,_e,_x,_t,_p,_o,_f,_r){\n    var _ext = {};\n    /**\n     * 取模板随机数种子\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/template/jst'\n     * ],function(_p){\n     *     // 返回一个标识符\n     *     var _seed = _p._$seed();\n     * });\n     * ```\n     *\n     * @method module:util/template/jst._$seed\n     * @return {String} 随机数种子\n     */\n    _p._$seed = TrimPath.seed;\n    /**\n     * 根据模板的序列号合并模板数据\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/template/jst'\n     * ],function(_p){\n     *     // 添加模版\n     *     var _html_seed =  _p._$add('<div>${name}</div>');\n     *     // 生成结构<div>jack</div>\n     *     var _html = _p._$get(_html_seed,{name:'jack'});\n     * });\n     * ```\n     *\n     * @method module:util/template/jst._$get\n     * @see    module:util/template/jst._$add\n     * @param  {String} arg0 - 模板序列号\n     * @param  {Object} arg1 - 模板数据\n     * @param  {Object} arg2 - 扩展接口\n     * @return {String}        合并数据后的内容\n     */\n    _p._$get = (function(){\n        var _doInline = function(_id){\n            return !_p._$getTextTemplate?'':\n                    _p._$getTextTemplate(_id);\n        };\n        return function(_sn,_data,_extend){\n            _data = _data||{};\n            _data.inline = _doInline;\n            _extend = _u._$merge({},_ext,_extend);\n            _extend.rand = _u._$uniqueID;\n            _extend.format = _u._$format;\n            _extend.escape = _u._$escape;\n            _extend.inline = _doInline;\n            return TrimPath.merge(_sn,_data,_extend);\n        };\n    })();\n    /**\n     * 添加JST模板，JST模板可以是节点的值\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/template/jst'\n     * ],function(_p){\n     *     // 添加模版缓存\n     *     var _html_seed =  _p._$add('<div>${name}</div>');\n     * });\n     * ```\n     *\n     * @method module:util/template/jst._$add\n     * @see    module:util/template/jst._$get\n     * @param  {String}  arg0 - JST模板内容或者节点ID\n     * @param  {Boolean} arg1 - 是否保留节点\n     * @return {String}         JST模板在缓存中的序列号\n     */\n    _p._$add = function(_content,_keep){\n        if (!_content) return '';\n        var _sn,_element = _e._$get(_content);\n        if (!!_element){\n            _sn = _element.id;\n            _content = _element.value||_element.innerText;\n            if (!_keep) _e._$remove(_element);\n        }\n        return TrimPath.parse(_content,_sn);\n    };\n    /**\n     * 添加JST模板内容\n     * \n     * @method module:util/template/jst._$addTemplate\n     * @see    module:util/template/jst._$add\n     * @param  {String}  arg0 - JST模板内容\n     * @param  {String}  arg1 - 模板标识\n     * @return {String}         JST模板在缓存中的序列号\n     */\n    _p._$addTemplate = function(_content,_sn){\n        return TrimPath.parse(_content,_sn);\n    };\n    /**\n     * 整合模板后输出至指定容器节点\n     *\n     * 结构举例\n     * ```html\n     * <div id=\"box\">aaa</div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/template/jst'\n     * ],function(_p){\n     *     // 添加模版缓存\n     *     var _html_seed =  _p._$add('<div>${name}</div>');\n     *     // 把结构塞到box中，生成<div id=\"box\"><div>jack</div></div>\n     *     _p._$render('box',_html_seed,{name:'jack'});\n     * });\n     * ```\n     *\n     * @method module:util/template/jst._$render\n     * @param  {String|Node} arg0 - 容器节点\n     * @param  {String}      arg1 - 模板序列号\n     * @param  {Object}      arg2 - 模板数据\n     * @param  {Object}      arg3 - 扩展接口\n     * @return {Void}\n     */\n    /**\n     * @method CHAINABLE._$render\n     * @see module:util/template/jst._$render\n     */\n    _p._$render = function(_parent,_sn,_data,_extend){\n        _parent = _e._$get(_parent);\n        if (!!_parent){\n            _parent.innerHTML =\n                _p._$get(_sn,_data,_extend);\n        }\n    };\n    /**\n     * 注册JST扩展方法\n     *\n     * 结构举例\n     * ```html\n     * <textarea name=\"jst\" id=\"abc\">\n     *   <div>\n     *     <p>${name|a|b}</p>\n     *   </div>\n     * </textarea>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/template/jst'\n     * ],function(_p){\n     *     // 注册扩展方法 a和b\n     *     _p._$extend({\n     *         a:function(){},\n     *         b:function(){}\n     *     });\n     *     // 模板整合数据\n     *     _p._$render(\n     *         'box','abc',{name:'jack'}\n     *     );\n     * });\n     * ```\n     *\n     * @method module:util/template/jst._$extend\n     * @param  {Object} arg0 - 扩展方法\n     * @return {Void}\n     */\n    _p._$extend = function(_map){\n        _u._$merge(_ext,_map);\n    };\n    // for chainable method\n    _x._$merge({_$render:_p._$render});\n\n    if (CMPT){ \n        var _z = NEJ.P('nej.e');\n        _z._$addHtmlTemplate     = _p._$add;\n        _z._$getHtmlTemplate     = _p._$get;\n        _z._$getHtmlTemplateSeed = _p._$seed;\n        _z._$renderHtmlTemplate  = _p._$render;\n        _z._$registJSTExt        = _p._$extend;\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/template/test/jst.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>jst测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit jst test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <textarea name=\"jst\" id=\"jst-box\">\n            <div>${name}</div>\n        </textarea>\n        <textarea name=\"txt\" id=\"txt-box\">\n            <div>pure text</div>\n        </textarea>\n        <textarea name=\"ntp\" id=\"ntp-box\">\n            <div>ntp</div>\n        </textarea>\n        <div id=\"item-box\"></div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./jst.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/template/test/jst.test.js",
    "content": "NEJ.define([\n    'util/template/jst'\n],function(_t){\n    var _e = NEJ.P('nej.e');\n    var _html;\n    test('getTemplateSeed',function(){\n        var _seed = _t._$seed();\n        equal(typeof(_seed),'number','seed是数字');\n        equal(_seed>0,true,'seed长度大于0');\n    });\n\n    test('addTemplate',function(){\n        _html = _t._$add('<div id=\"${name}\">name</div>');\n        equal(typeof(_html),'string','返回id是字符串');\n        equal(_html.length>0,true,'返回id长度大于0');\n    });\n\n    test('getTemplate',function(){\n        _html = _t._$add('<div id=\"${name}\">name</div>');\n        var _htmltmp = _t._$get(_html);\n        equal(_htmltmp,'<div id=\"\">name</div>','成功根据id获取html');\n    });\n\n    test('renderTemplate',function(){\n        _t._$render('item-box',_html,{name:'cheng-lin'});\n        equal(_e._$getChildren(_e._$get('item-box'))[0].id,'cheng-lin','成功渲染了模版');\n    });\n\n    test('registJSTExt',function(){\n        _t._$extend({\n            freplace:function(_str){\n                return (_str||'').replace(/-/,'');\n            }\n        })\n        _html = _t._$add('<div id=\"${name|freplace}\">name</div>');\n        _t._$render('item-box',_html,{name:'cheng-lin'});\n         equal(_e._$getChildren(_e._$get('item-box'))[0].id,'chenglin','注册的方法截掉了中间的-');\n    });\n\n});"
  },
  {
    "path": "src/util/template/test/myItem.js",
    "content": "var f = function(){\n\tvar _  = NEJ.P,\n\t    _p = _('nej.ut'),\n\t\t_e = _('nej.e'),\n\t\t_v = _('nej.v'),\n\t\t_u = _('nej.ui'),\n\t\t_proMyItem;\n\tvar _html_key = _e._$addNodeTemplate('<div>123</div>');\n    _p._$$MyItem = NEJ.C();\n\t_proMyItem = _p._$$MyItem._$extend(_u._$$Item);\n\t\n\t\n\t_proMyItem.__reset = function(_options){\n\t\tthis.__data = _options.data;\n\t\tthis.__supReset(_options);\n\t}\n\t/**\n\t * 刷新一项的信息\n\t */\n\t_proMyItem.__doRefresh = function(){\n\t\tthis.__body.innerText = this.__data.name;\n\t};\n\t\n\t_proMyItem.__initXGui = function(){\n        this.__seed_html = _e._$getNodeTemplate(_html_key);\n    };\n};\ndefine('{pro}myItem.js',['{lib}ui/item/item.js'],f)\n"
  },
  {
    "path": "src/util/template/test/tpl.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>tpl测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit tpl test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n\t\t<textarea name=\"jst\" id=\"jst-box\">\n\t\t\t<div>${name}</div>\n\t\t</textarea>\n\t\t<textarea name=\"txt\" id=\"txt-box\">\n            <div>pure text</div>\n        </textarea>\n\t\t<textarea name=\"ntp\" id=\"ntp-box\">\n            <div>ntp</div>\n        </textarea>\n\t\t<textarea name=\"js\" id=\"js-box\" data-src='/nej-baseline/src/define.js'></textarea>\n\t\t<textarea name=\"css\" id=\"css-box\" data-src='/nej-baseline/qunit/base/qunit.css'></textarea>\n\t\t<textarea name=\"html\" id=\"html-box\" data-src='/nej-baseline/qunit/html/ui/audioTest.html'></textarea>\n\t\t<textarea name=\"res\" id=\"res-box\" data-src='http://pagea.xxx/'></textarea>\n        <div id=\"item-box\"></div>\n       <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./tpl.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/template/test/tpl.test.js",
    "content": "var f = function(){\n    //定义测试模块\n    module(\"tpl\");\n\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n\t\t_p = _('nej.ut');\n\n    test('jst',function(){\n        _e._$parseTemplate('jst-box');\n\t\tvar _content = _e._$get('jst-box',{name:'jack'});\n\t\tequal(_content,'<div>jack</div>','解析结果与预期相同');\n    });\n\n\n\ttest('txt',function(){\n        _e._$parseTemplate('txt-box');\n        var _content = _e._$getTextTemplate('txt-box').trim();\n        equal(_content,'<div>pure text</div>','解析结果与预期相同');\n    });\n\n\ttest('ntp',function(){\n        _e._$parseTemplate('ntp-box');\n        var _content = _e._$getNodeTemplate('ntp-box',{name:'sean'});\n        equal(_content.innerText,'ntp','解析结果与预期相同');\n    });\n\n\ttest('js',function(){\n        _e._$parseTemplate('js-box');\n\t\tok(true,'会load一个js文件');\n    });\n\n\ttest('css',function(){\n        _e._$parseTemplate('css-box');\n\t\tok(true,'会load一个css文件');\n    });\n\n\ttest('html',function(){\n        _e._$parseTemplate('html-box');\n\t\tok(true,'会load一个html文件');\n    });\n\n\ttest('res',function(){\n        _e._$parseTemplate('res-box');\n\t\tok(true,'加载纯文本文件');\n    });\n\n\ttest('item',function(){\n        expect(0)\n\t\t_e._$getItemTemplate([{name:'jack'},{name:'sean'}],_p._$$MyItem,{parent:'item-box'});\n\t});\n}\nmodule('依赖模块');\ntest('define',function(){expect(0);\n    define('{pro}tpl.test.js',\n    ['{lib}util/template/tpl.js','{pro}myItem.js'],f);\n});\n"
  },
  {
    "path": "src/util/template/tpl.js",
    "content": "/*\n * ------------------------------------------\n * 模板管理接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/template/tpl */\nNEJ.define([\n    'base/global',\n    'base/util',\n    'base/event',\n    'base/element',\n    'base/platform',\n    'util/template/jst',\n    'util/event/event',\n    'util/ajax/tag',\n    'util/ajax/xdr',\n    'base/chain'\n],function(NEJ,_u,_v,_e,_b,_y,_t,_j0,_j1,_x,_p,_o,_f,_r){\n    var _cache = {}, // template cache\n        _skey  = 'ntp-'+(+new Date)+'-';\n    // only for test\n    _p.tpl = function(){\n        return _cache;\n    };\n    /**\n     * 解析模板集合\n     *\n     * 结构举例\n     * ```html\n     * <textarea name=\"jst\" id=\"jst-box\">\n     *     <div>${name}</div>\n     * </textarea>\n     * <textarea name=\"txt\" id=\"txt-box\">\n     *     <div>pure text</div>\n     * </textarea>\n     * <textarea name=\"ntp\" id=\"ntp-box\">\n     *     <div>ntp</div>\n     * </textarea>\n     * <textarea name=\"js\" id=\"js-box\" data-src='/nej-baseline/src/define.js'></textarea>\n     * <textarea name=\"css\" id=\"css-box\" data-src='/nej-baseline/qunit/base/qunit.css'></textarea>\n     * <textarea name=\"html\" id=\"html-box\" data-src='/nej-baseline/qunit/html/ui/audioTest.html'></textarea>\n     * <textarea name=\"res\" id=\"res-box\" data-src='http://pagead2.googlesyndication.com/simgad/15167196758298977737'></textarea>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/template/tpl'\n     * ],function(_p){\n     *     // 调用_$add接口缓存模版，id为key\n     *     // 要用的时候通过_$get(key,{数据})合并模版后返回字符串\n     *     _p._$parseTemplate('jst-box');\n     *     // 生成结果：<div>jack</div>\n     *     _p._$getTextTemplate('jst-box').trim();\n     *\n     *     // 通过_$addTextTemplate接口缓存纯文本,id为key\n     *     _p._$parseTemplate('txt-box');\n     *     // 要用的时候通过_e._$getTextTemplate(key)取到纯文本\n     *     _p._$getTextTemplate('txt-box')\n     *\n     *\n     *     // 通过_$addNodeTemplate接口缓存节点，第一次如果是字符串，缓存字符串，id为key\n     *     _p._$parseTemplate('ntp-box');\n     *     // 要用的时候通过_$getNodeTemplate('ntp-box')取出节点，\n     *     // 如果缓存中是字符串,取的时候要重新转换成节点，然后重新缓存一边，下次直接是取节点\n     *     _p._$getNodeTemplate('ntp-box');\n     *\n     *     // 加载id为js-box的textarea节点data-src指定的js文件\n     *     _p._$parseTemplate('js-box');\n     *\n     *     // 加载id为css-box的textarea节点data-src指定的css文件\n     *     _p._$parseTemplate('css-box');\n     *\n     *     // 加载id为html-box的textarea节点data-src指定的html文件\n     *     _p._$parseTemplate('html-box');\n     *\n     *     // 加载id为res-box的textarea节点data-src指定的纯文本文件\n     *     _p._$parseTemplate('res-box');\n     * });\n     * ```\n     *\n     * @method   module:util/template/tpl._$parseTemplate\n     * @param    {String|Node} arg0 - 模板集合节点\n     * @param    {Object}      arg1 - 可选配置参数\n     * @property {String}      root - 根路径，相对规则\n     * @return   {Void}\n     */\n    /**\n     * @method CHAINABLE._$parseTemplate\n     * @see module:util/template/tpl._$parseTemplate\n     */\n    _p._$parseTemplate = (function(){\n        // support textarea/script tag for template\n        var fmap = {\n            text: 'txt',\n            plain: 'txt',\n            javascript:'js'\n        };\n        var nmap = {\n            textarea: {\n                getType: function (node){\n                    var type = node.name.toLowerCase();\n                    return fmap[type]||type;\n                },\n                getContent: function (node){\n                    return node.value||node.innerText||'';\n                }\n            },\n            script: {\n                getType: function (node) {\n                    var type = (node.type||'').toLowerCase().replace(/^nej\\//i,'');\n                    return fmap[type]||type;\n                },\n                getContent: function (node){\n                    return node.innerText||node.innerHTML||'';\n                }\n            }\n        };\n        // support template ready event\n        var _count = 0;\n        var _doCheckReady = function(){\n            if (_count>0) return;\n            _count = 0;\n            _v._$dispatchEvent(document,'templateready');\n            _v._$clearEvent(document,'templateready');\n        };\n        var _doParseSrc = function(_textarea,_options){\n            var _src = _e._$dataset(_textarea,'src');\n            if (!_src) return;\n            _options = _options||_o;\n            var _root = _options.root;\n            if (!_root){\n                _root = _textarea.ownerDocument.location.href;\n            }else{\n                _root = _u._$absolute(_root);\n            }\n            _src = _src.split(',');\n            _u._$forEach(_src,function(_value,_index,_list){\n                _list[_index] = _u._$absolute(_value,_root);\n            });\n            return _src;\n        };\n\n        var _doAddStyle = function(_textarea,_options){\n            if (!_textarea) return;\n            var _src = _doParseSrc(_textarea,_options);\n            if (!!_src){\n                _j0._$queueStyle(_src,{\n                    version:_e._$dataset(_textarea,'version')\n                });\n            }\n            var tag = _textarea.tagName.toLowerCase();\n            _e._$addStyle(nmap[tag].getContent(_textarea));\n        };\n        var _onAddScript = function(_value){\n            _count--;\n            _e._$addScript(_value);\n            _doCheckReady();\n        };\n        var _doAddScript = function(_textarea,_options){\n            if (!_textarea) return;\n            var _src = _doParseSrc(_textarea,_options),\n                _tag = _textarea.tagName.toLowerCase(),\n                _val = nmap[_tag].getContent(_textarea);\n            if (!!_src){\n                _count++;\n                var _options = {\n                    version:_e._$dataset(_textarea,'version'),\n                    onload:_onAddScript._$bind(null,_val)\n                };\n                window.setTimeout(\n                    _j0._$queueScript._$bind(\n                        _j0,_src,_options\n                    ),0\n                );\n                return;\n            }\n            _e._$addScript(_val);\n        };\n        var _onAddHtml = function(_body){\n            _count--;\n            _p._$parseTemplate(_body);\n            _doCheckReady();\n        };\n        var _doAddHtml = function(_textarea,_options){\n            if (!_textarea) return;\n            var _src = _doParseSrc(_textarea,_options)[0];\n            if (!!_src){\n                _count++;\n                var _options = {\n                    version:_e._$dataset(_textarea,'version'),\n                    onload:_onAddHtml\n                };\n                window.setTimeout(\n                    _j0._$loadTemplate._$bind(\n                        _j0,_src,_options\n                    ),0\n                );\n            }\n        };\n        var _onAddTextResource = function(_id,_text){\n            _count--;\n            _p._$addTextTemplate(_id,_text||'');\n            _doCheckReady();\n        };\n        var _doAddTextResource = function(_textarea,_options){\n            if (!_textarea||!_textarea.id) return;\n            var _id = _textarea.id,\n                _src = _doParseSrc(_textarea,_options)[0];\n            if (!!_src){\n                _count++;\n                var _url = _src+(_src.indexOf('?')<0?'?':'&')+\n                          (_e._$dataset(_textarea,'version')||''),\n                    _options = {\n                        type:'text',\n                        method:'GET',\n                        onload:_onAddTextResource._$bind(null,_id)\n                    };\n                window.setTimeout(\n                    _j1._$request._$bind(\n                        _j1,_url,_options\n                    ),0\n                );\n            }\n        };\n        var _doDumpContent = function(_node){\n            // bugfix textarea content not corrent for safari in mac\n            if (_b._$is('mac')&&_b._$KERNEL.browser==='safari'){\n                return _u._$unescape(_node.innerHTML);\n            }else{\n                return nmap[_node.tagName.toLowerCase()].getContent(_node);\n            }\n        };\n        var _doAddTemplate = function(_node,_options){\n            var conf = nmap[_node.tagName.toLowerCase()],\n                _type = conf.getType(_node);\n            //console.debug(_type+'<'+_node.id+'> : '+_node.value.replace(/\\n/g,' '));\n            switch(_type){\n                case 'jst':\n                    _y._$addTemplate(_doDumpContent(_node),_node.id);\n                return;\n                case 'txt':\n                    _p._$addTextTemplate(_node.id,_doDumpContent(_node));\n                return;\n                case 'ntp':\n                    _p._$addNodeTemplate(_doDumpContent(_node),_node.id);\n                return;\n                case 'js':\n                    _doAddScript(_node,_options);\n                return;\n                case 'css':\n                    _doAddStyle(_node,_options);\n                return;\n                case 'html':\n                    _doAddHtml(_node,_options);\n                return;\n                case 'res':\n                    _doAddTextResource(_node,_options);\n                return;\n            }\n        };\n        // dump script support\n        var doDumpScript = function (node) {\n            var ret = [],\n                list = node.getElementsByTagName('script');\n            // try dump from head\n            if ((!list||!list.length)&&node.tagName==='BODY'){\n                list = node.ownerDocument.getElementsByTagName('script');\n            }\n            _u._$forEach(list,function (it) {\n                if (it.type.search(/^nej\\//i)===0){\n                    ret.push(it);\n                }\n            });\n            return ret;\n        };\n        /**\n         * 模版准备完毕触发事件，包括所有外联模版载入完成\n         *\n         * 结构举例\n         * ```html\n         * <div id=\"template-box\">\n         *   <textarea name=\"jst\">\n         *     jst tempalte here\n         *   </textarea>\n         *   <!-- text template with id=\"txt-id-1\" in widget.html -->\n         *   <textarea name=\"html\" data-src=\"./widget.html\"></textarea>\n         * </div>\n         * ```\n         *\n         * 脚本举例\n         * ```javascript\n         * NEJ.define([\n         *     'base/event'\n         *     'util/template/tpl'\n         * ],function(_v,_e){\n         *     // 解析模版集合\n         *     _e._$parseTemplate('template-box');\n         *\n         *     // 在templateready事件中使用外联模版可以保证正确性\n         *     _v._$addEvent(\n         *         document,'templateready',\n         *         function(_event){\n         *             var _text = _e._$getTextTemplate('txt-id-1');\n         *             // TODO\n         *         }\n         *     );\n         * });\n         * ```\n         *\n         * @event    external:document.ontemplateready\n         * @param    {Object} event - 事件信息\n         */\n        _t._$$CustomEvent._$allocate({\n            element:document,\n            event:'templateready',\n            oneventadd:_doCheckReady\n        });\n        return function(_element,_options){\n            _element = _e._$get(_element);\n            if (!!_element){\n                var _list,\n                    _tag = _element.tagName;\n                if (_tag==='TEXTAREA'||_tag==='SCRIPT'){\n                    _list = [_element];\n                }else{\n                    _list = _u._$object2array(\n                        _element.getElementsByTagName('textarea')\n                    );\n                    _list.push.apply(_list, doDumpScript(_element))\n                }\n                _u._$forEach(_list,function(_node){\n                    // console.log(_node);\n                    _doAddTemplate(_node,_options);\n                });\n                _e._$remove(_element,!0);\n            }\n            _doCheckReady();\n        };\n    })();\n    /**\n     * 添加文本模板\n     *\n     * 脚本举例\n     * ```javascript\n     * // 通过_e._$addTextTemplate接口缓存纯文本,id为key\n     * _e._$addTextTemplate('txt-box','i am content');\n     * // 要用的时候通过_e._$getTextTemplate(key)取到纯文本\n     * _e._$getTextTemplate('txt-box')\n     * ```\n     *\n     * @method module:util/template/tpl._$addTextTemplate\n     * @see    module:util/template/tpl._$getTextTemplate\n     * @param  {String} arg0 - 模板键值\n     * @param  {String} arg1 - 模板内容\n     * @return {Void}\n     */\n    _p._$addTextTemplate = function(_key,_value){\n        if (_cache[_key]!=null&&((typeof _cache[_key])===(typeof _value))){\n            console.warn('text template overwrited with key '+_key);\n            console.debug('old template content: '+_cache[_key].replace(/\\n/g,' '));\n            console.debug('new template content: '+_value.replace(/\\n/g,' '));\n        }\n        _cache[_key] = _value||'';\n    };\n    /**\n     * 取文本模板\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/template/tpl'\n     * ],function(_p){\n     *     // 通过_$addTextTemplate接口缓存纯文本,id为key\n     *     _p._$addTextTemplate('txt-box','i am content');\n     *     // 要用的时候通过_$getTextTemplate(key)取到纯文本\n     *     _p._$getTextTemplate('txt-box')\n     * });\n     * ```\n     *\n     * @method module:util/template/tpl._$getTextTemplate\n     * @see    module:util/template/tpl._$addTextTemplate\n     * @param  {String} arg0 - 模板键值\n     * @return {String}        模板内容\n     */\n    _p._$getTextTemplate = function(_key){\n        return _cache[_key]||'';\n    };\n    /**\n     * 添加节点模板\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/template/tpl'\n     * ],function(_p){\n     *     // 通过_$addNodeTemplate接口缓存节点，第一次如果是字符串，缓存字符串，id为key\n     *     _p._$addNodeTemplate(node,'ntp-box');\n     *     // 要用的时候通过_$getNodeTemplate('ntp-box')取出节点，\n     *     // 如果缓存中是字符串,取的时候要重新转换成节点，然后重新缓存一边，下次直接是取节点\n     *     _p._$getNodeTemplate('ntp-box');\n     * });\n     * ```\n     *\n     * @method module:util/template/tpl._$addNodeTemplate\n     * @see    module:util/template/tpl._$getNodeTemplate\n     * @param  {String|Node} arg0 - 模板\n     * @param  {String}      arg1 - 模板序列号\n     * @return {String}             模板序列号\n     */\n    /**\n     * @method CHAINABLE._$addNodeTemplate\n     * @see module:util/template/tpl._$addNodeTemplate\n     */\n    _p._$addNodeTemplate = function(_element,_key){\n        _key = _key||_u._$uniqueID();\n        _element = _e._$get(_element)||_element;\n        _p._$addTextTemplate(_skey+_key,_element);\n        if (!_u._$isString(_element)){\n            _e._$removeByEC(_element);\n        }\n        return _key;\n    };\n    /**\n     * 取节点模板\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/template/tpl'\n     * ],function(_p){\n     *     // 通过_$addNodeTemplate接口缓存节点，第一次如果是字符串，缓存字符串，id为key\n     *     _p._$addNodeTemplate('txt-box');\n     *     // 要用的时候通过_$getNodeTemplate('ntp-box')取出节点，\n     *     // 如果缓存中是字符串,取的时候要重新转换成节点，然后重新缓存一边，下次直接是取节点\n     *     _p._$getNodeTemplate('ntp-box');\n     * });\n     * ```\n     *\n     * @method module:util/template/tpl._$getNodeTemplate\n     * @see    module:util/template/tpl._$addNodeTemplate\n     * @param  {String} arg0 - 模板序列号\n     * @return {Node}          节点模板\n     */\n    _p._$getNodeTemplate = function(_key){\n        if (!_key) return null;\n        _key = _skey+_key;\n        var _value = _p._$getTextTemplate(_key);\n        if (!_value) return null;\n        var _node;\n        if (_u._$isString(_value)){\n            _value = _e._$html2node(_value);\n            // bugfix: https://connect.microsoft.com/IE/feedback/details/811408\n            var _list = _value.getElementsByTagName('textarea');\n            if (_value.tagName!='TEXTAREA'&&\n               (!_list||!_list.length)){\n                _p._$addTextTemplate(_key,_value);\n            }else{\n                _node = _value;\n            }\n        }\n        // clone node and push to memory\n        if (!_node){\n            _node = _value.cloneNode(!0);\n        }\n        _e._$removeByEC(_node);\n        return _node;\n    };\n    /**\n     * 取ITEM模板列表\n     *\n     * 结构举例\n     * ```html\n     * <div id=\"item-box\"></div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'base/klass',\n     *     'ui/item/item',\n     *     'util/template/tpl'\n     * ],function(_k,_i,_t,_p){\n     *     var _pro;\n     *     var _html_key = _t._$addNodeTemplate('<div>123</div>');\n     *\n     *     _p._$$MyItem = _k._$klass();\n     *     _pro = _p._$$MyItem._$extend(_i._$$Item);\n     *\n     *     _pro.__reset = function(_options){\n     *         this.__data = _options.data;\n     *         this.__super(_options);\n     *     }\n     *\n     *     _pro.__doRefresh = function(){\n     *         this.__body.innerText = this.__data.name;\n     *     };\n     *\n     *     _pro.__initXGui = function(){\n     *         this.__seed_html = _html_key;\n     *     };\n     *\n     *     return _p;\n     * });\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     '/path/to/my/item.js',\n     *     'util/template/tpl'\n     * ],function(_t,_p){\n     *     // _$getItemTemplate接口生成item列表\n     *     // 返回一个item的列表，可以循环调用_$recycle()，来销毁\n     *     var _items = _p._$getItemTemplate(\n     *         [{name:'jack'},{name:'sean'}],\n     *         _t._$$MyItem,{parent:'item-box'}\n     *     );\n     * });\n     * ```\n     *\n     * @method   module:util/template/tpl._$getItemTemplate\n     * @param    {Array}   arg0   - 数据列表\n     * @param    {module:ui/item/item._$$Item} arg1   - 列表项构造函数\n     * @param    {Object}  arg2   - 可选配置参数，其他参数参见item指定的构造函数的配置参数\n     * @property {Number}  offset - 起始指针【包含】，默认0\n     * @property {Number}  limit  - 分配数据长度或者数量，默认为列表长度\n     * @return   {Array}            ITEM模板列表\n     */\n    _p._$getItemTemplate = (function(){\n        var _doFilter = function(_value,_key){\n            return _key=='offset'||_key=='limit';\n        };\n        return function(_list,_item,_options){\n            var _arr = [];\n            if (!_list||!_list.length||!_item){\n                return _arr;\n            }\n            _options = _options||_o;\n            var _len = _list.length,\n                _beg = parseInt(_options.offset)||0,\n                _end = Math.min(_len,_beg+(\n                       parseInt(_options.limit)||_len)),\n                _opt = {total:_list.length,range:[_beg,_end]};\n            _u._$merge(_opt,_options,_doFilter);\n            for(var i=_beg,_instance;i<_end;i++){\n                _opt.index = i;\n                _opt.data = _list[i];\n                _instance = _item._$allocate(_opt);\n                var _id = _instance._$getId();\n                _cache[_id] = _instance;\n                _instance._$recycle =\n                _instance._$recycle._$aop(\n                    function(_id,_instance){\n                        delete _cache[_id];\n                        delete _instance._$recycle;\n                    }._$bind(null,_id,_instance));\n                _arr.push(_instance);\n            }\n            return _arr;\n        };\n    })();\n    /**\n     * 根据ID取列表项对象\n     *\n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/template/tpl'\n     * ],function(_p){\n     *     // 通过id拿某一项item\n     *     // id是生成item的时候，'itm'+日期字符串生成,存在于_instance.__id变量中\n     *     var _item = _p._$getItemById('itm-123');\n     * });\n     * ```\n     *\n     * @method module:util/template/tpl._$getItemById\n     * @param  {String} arg0 - 列表项\n     * @return {module:ui/item/item._$$Item} 列表项实例\n     */\n    _p._$getItemById = function(_id){\n        return _cache[_id];\n    };\n    /**\n     * 解析UI模板集合\n     *\n     * @method module:util/template/tpl._$parseUITemplate\n     * @param  {String} html - 待解析字符串\n     * @param  {Object} map  - 模版id的对应map\n     * @return {Object} 模版id的map\n     */\n    _p._$parseUITemplate = (function(){\n        var _reg = /#<(.+?)>/g;\n        return function(_html,_map){ // {abc:'eeee'} // #<abc>\n            _map = _map||{};\n            _html = (_html||'').replace(_reg,function($1,$2){\n                var _id = _map[$2];\n                if (!_id){\n                    _id = 'tpl-'+_u._$uniqueID();\n                    _map[$2] = _id;\n                }\n                return _id;\n            });\n            //console.debug('template source code -> '+_html.replace(/\\n/g,' '));\n            /*\n            _u._$forIn(\n                _element.getElementsByTagName('textarea'),\n                function(_textarea){\n                    _textarea.id = (_textarea.id||'').replace(\n                        _reg,function($1,$2){\n                            var _id = _map[$2];\n                            if (!_id){\n                                _id = 'tpl-'+_u._$uniqueID();\n                                _map[$2] = _id;\n                            }\n                            return _id;\n                        }\n                    );\n                }\n            );\n            */\n            _p._$parseTemplate(\n                _e._$html2node(_html)\n            );\n            return _map;\n        };\n    })();\n    // for chainable method\n    _x._$merge({\n        _$parseTemplate:_p._$parseTemplate,\n        _$addNodeTemplate:_p._$addNodeTemplate\n    });\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.e'),_p);\n    }\n\n    return _p;\n});\n"
  },
  {
    "path": "src/util/template/trimpath.js",
    "content": "/*\n * TrimPath Template. Release 1.1.2.\n * Copyright (C) 2004 - 2007 TrimPath.\n * \n * TrimPath Template is licensed under the GNU General Public License\n * and the Apache License, Version 2.0, as follows:\n *\n * This program is free software; you can redistribute it and/or \n * modify it under the terms of the GNU General Public License\n * as published by the Free Software Foundation; either version 2\n * of the License, or (at your option) any later version.\n * \n * This program is distributed WITHOUT ANY WARRANTY; without even the \n * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  \n * See the GNU General Public License for more details.\n * \n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * \n * http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/*\n * ------------------------------------------\n * JST模板引擎实现文件\n * 实现原理参考trimpath项目 (GPL & APL)\n * http://code.google.com/p/trimpath/\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n(function(){\n    /**\n     * TrimPath模版引擎名字空间\n     * @namespace TrimPath\n     */\n    // init TrimPath\n    if (typeof TrimPath==='undefined'){\n        TrimPath = {};\n        if (typeof exports!=='undefined')\n            TrimPath = exports;\n    }else{\n        return;\n    }\n    // variable declaration\n    var _tcache = {}, // jst string cache\n        _stack  = [], // loop statement stack\n        _rspc   = /\\s+/g,\n        _seed   = +new Date,\n        _trim,_config,_vars;\n    /*\n     * 解析表达式中变量信息，如\n     * a.b(c,d) || d('aaaa',f,g) && !!test() || 'eeee'\n     * @param  {String} 内容\n     * @return {Void}\n     */\n    var _doParseVars = (function(){\n        var _reg0 = /^\\s*[\\[\\{'\"].*?[\\]\\}'\"]\\s*$/,\n            _reg1 = /[\\&\\|\\<\\>\\+\\-\\*\\/\\%\\,\\(\\)\\[\\]\\?\\:\\!\\=\\;]/,\n            // keyword extend later\n            _reg2 = /^(?:defined|null|undefined|true|false|instanceof|new|this|typeof|\\$v|[\\d]+)$/i,\n            // statement extend later\n            // new XX\n            _reg3 = /^new\\s+/,\n            _reg4 = /['\"]/;\n        var _doParseSimple = function(_value){\n            if (_reg0.test(_value)) return;\n            _value = _value.split('.')[0].trim();\n            if (!_value||_reg4.test(_value)) return;\n            _value = _value.replace(_reg3,'');\n            //console.log('-->'+_value+'<--');\n            try{\n                if (_reg2.test(_value))\n                    return;\n                _vars[_value] = 1;\n                //console.log('=====>'+_value+'<====');\n            }catch(e){\n                // ignore\n            }\n        };\n        return function(_content){\n            _content = _content||'';\n            // for string/array\n            if (!_content||_reg0.test(_content)) \n                return;\n            var _arr = _content.split(_reg1);\n            for(var i=0,l=_arr.length;i<l;i++)\n                _doParseSimple(_arr[i]);\n        };\n    })();\n    /*\n     * 解析{for x in b}字符串的前缀\n     * @param  {Array}  按空格拆分的值,['for','x','in','b']\n     * @return {String} 解析后的前缀值\n     */\n    var _doParsePrefixFor = function(_part){\n        if (_part[2]!='in')\n            throw 'bad for loop statement: '+_part.join(' ');\n        _stack.push(_part[1]);\n        // b is array or has [1,2,4],{a:'aaa',b:'bbb'}\n        _doParseVars(_part[3]);\n        return 'var __HASH__'+_part[1]+' = '+_part[3]+','+\n                    _part[1]+','+_part[1]+'_count=0;'+\n               'if (!!__HASH__'+_part[1]+')'+\n                   'for(var '+_part[1]+'_key in __HASH__'+_part[1]+'){'+\n                        _part[1]+' = __HASH__'+_part[1]+'['+_part[1]+'_key];'+\n                        'if (typeof('+_part[1]+')==\"function\") continue;'+\n                        _part[1]+'_count++;';\n    };\n    /*\n     * 解析{forelse}字符串的前缀\n     * @return {String} 解析后的前缀值\n     */\n    var _doParsePrefixForElse = function(){\n        var _part = _stack[_stack.length-1];\n        return '}; if(!__HASH__'+_part+'||!'+_part+'_count){';\n    };\n    /*\n     * 解析{/for}字符串的前缀\n     * @return {String} 解析后的前缀值\n     */\n    var _doParsePrefixForEnd = function(){\n        _stack.pop();\n        return '};';\n    };\n    /*\n     * 解析{list seq as x}或者{list 1..100 as x}字符串的前缀\n     * @param  {Array}  按空格拆分的值,['list','seq','as','x']\n     * @return {String} 解析后的前缀值\n     */\n    var _doParsePrefixList = function(_part){\n        if (_part[2]!='as')\n            throw 'bad for list loop statement: '+_part.join(' ');\n        var _seq = _part[1].split('..');\n        if (_seq.length>1){\n            // {list 1..100 as x}\n            _doParseVars(_seq[0]);\n            _doParseVars(_seq[1]);\n            return 'for(var '+_part[3]+','+_part[3]+'_index=0,'+\n                        _part[3]+'_beg='+_seq[0]+','+_part[3]+'_end='+_seq[1]+','+\n                        _part[3]+'_length=parseInt('+_part[3]+'_end-'+_part[3]+'_beg+1);'+\n                        _part[3]+'_index<'+_part[3]+'_length;'+_part[3]+'_index++){'+\n                        _part[3]+' = '+_part[3]+'_beg+'+_part[3]+'_index;';\n        }else{\n            // {list seq as x}\n            // seq is array [1,2,4]\n            _doParseVars(_part[1]);\n            return 'for(var __LIST__'+_part[3]+' = '+_part[1]+','+\n                        _part[3]+','+_part[3]+'_index=0,'+\n                        _part[3]+'_length=__LIST__'+_part[3]+'.length;'+\n                        _part[3]+'_index<'+_part[3]+'_length;'+_part[3]+'_index++){'+\n                        _part[3]+' = __LIST__'+_part[3]+'['+_part[3]+'_index];';\n        }\n    };\n    /*\n     * 解析{macro macroName(arg1,arg2,...argN)}字符串的前缀\n     * @param  {Array}  按空格拆分的值,['macro','macroName(arg1,arg2,...argN)']\n     * @return {String} 解析后的前缀值\n     */\n    var _doParsePrefixMacro = function(_part){\n        if (!_part||!_part.length) return;\n        _part.shift(); // remove macro key word\n        var _name = _part[0].split('(')[0];\n        return 'var '+_name+' = function'+_part.join('').replace(_name,'')+'{var __OUT=[];';\n    };\n    /*\n     * 解析{include \"text-template-id\"}字符串前缀\n     * @param  {Array}  按空格拆分的值,['include','\"text-template-id\"']\n     * @return {String} 解析后的前缀值\n     */\n    var _doParsePrefixInline = function(_part){\n        if (!_part[1]) \n            throw 'bad include statement: '+_part.join(' ');\n        return 'if (typeof inline == \"function\"){__OUT.push(inline(';\n    };\n    /**\n     * 解析IF语句前缀，{if customer != null && customer.balance > 1000 || test(customer)}\n     * @param  {String}  返回值\n     * @param  {Array}   按空格拆分的值\n     * @return {String}  解析后的前缀值\n     */\n    var _doParsePrefixCondition = function(_prefix,_part){\n        _doParseVars(_part.slice(1).join(' '));\n        return _prefix;\n    };\n    // parse prefix condition\n    var _doParsePrefixConditionIF = function(_part){\n        return _doParsePrefixCondition('if(',_part);\n    };\n    var _doParsePrefixConditionELSEIF = function(_part){\n        return _doParsePrefixCondition('}else if(',_part);\n    };\n    var _doParsePrefixConditionVAR = function(_part){\n        return _doParsePrefixCondition('var ',_part);\n    };\n    // jst configuration\n    _config = {\n        blk : /^\\{(cdata|minify|eval)/i,\n        tag : 'forelse|for|list|if|elseif|else|var|macro|break|notrim|trim|include',\n        // {pmin : min param number,\n        //  pdft : param default value,\n        //  pfix : statement prefix,\n        //  sfix : statement suffix}\n        def : {\n            'if'     : {pfix:_doParsePrefixConditionIF,sfix:'){',pmin:1},\n            'else'   : {pfix:'}else{'},\n            'elseif' : {pfix:_doParsePrefixConditionELSEIF,sfix:'){',pdft:'true'},\n            '/if'    : {pfix:'}'},\n            'for'    : {pfix:_doParsePrefixFor,pmin:3},\n            'forelse': {pfix:_doParsePrefixForElse},\n            '/for'   : {pfix:_doParsePrefixForEnd},\n            'list'   : {pfix:_doParsePrefixList,pmin:3},\n            '/list'  : {pfix:'};'},\n            'break'  : {pfix:'break;'},\n            'var'    : {pfix:_doParsePrefixConditionVAR,sfix:';'},\n            'macro'  : {pfix:_doParsePrefixMacro},\n            '/macro' : {pfix:'return __OUT.join(\"\");};'},\n            'trim'   : {pfix:function(){_trim = !0;}},\n            '/trim'  : {pfix:function(){_trim = null;}},\n            'inline' : {pfix:_doParsePrefixInline,pmin:1,sfix:'));}'}\n        },\n        ext : {\n            'seed'   : function(_prefix){return (_prefix||'')+''+_seed;},\n            'default': function(_value,_default){return _value||_default;}\n        }\n    };\n    /*\n     * 解析语句，如{if customer != null && customer.balance > 1000}\n     * @param  {String} 待解析语句\n     * @param  {Array}  内容输出\n     * @return {Void}\n     */\n    var _doParseStatement = (function(){\n        var _rbrc = /\\\\([\\{\\}])/g;\n        return function(_content,_out){\n            _content = _content.replace(_rbrc,'$1');\n            //console.log('++++>'+_content);\n            var _part = _content.slice(1, -1).split(_rspc),\n                _conf = _config.def[_part[0]];\n            if (!_conf){_doParseSectionText(_content,_out);return;}\n            if (!!_conf.pmin&&_conf.pmin>=_part.length)\n                throw 'Statement needs more parameters:'+_content;\n            // parse prefix\n            _out.push((!!_conf.pfix&&\n                       typeof(_conf.pfix)!='string')\n                       ?_conf.pfix(_part):(_conf.pfix||''));\n            // parse params and suffix\n            if (!!_conf.sfix){\n                if (_part.length<=1) {\n                    if (!!_conf.pdft) _out.push(_conf.pdft);\n                }else{\n                    for(var i=1,l=_part.length;i<l;i++){\n                        if (i>1) _out.push(' ');\n                        _out.push(_part[i]);\n                    }\n                }\n                _out.push(_conf.sfix);\n            }\n        };\n    })();\n    /*\n     * 解析表达式，如['firstName','default:\"John Doe\"','capitalize']\n     * @param  {Array}  表达式内容\n     * @param  {Number} 表达式索引\n     * @param  {Array}  内容输出\n     * @return {Void}\n     */\n    var _doParseExpression = function(_exps,_out){\n        // foo|a:x|b:y1,y2|c:z1,z2 -> c(b(a(foo,x),y1,y2),z1,z2)\n        if (!_exps||!_exps.length) return;\n        if (_exps.length==1){\n            var _var = _exps.pop();\n            _doParseVars(_var);\n            // fix error for ${}\n            _out.push(_var==''?'\"\"':_var);\n            return;\n        }\n        var _exp = _exps.pop().split(':');\n        _out.push('__MDF[\\''+_exp.shift()+'\\'](');\n        _doParseExpression(_exps,_out);\n        if (_exp.length>0){\n            var _args = _exp.join(':');\n            _doParseVars(_args);\n            _out.push(','+_args);\n        }\n        _out.push(')');\n    };\n    /*\n     * 解析内容，内容中可能包含换行\n     * @param  {String} 待解析语句\n     * @param  {Array}  内容输出\n     * @return {Void}\n     */\n    var _doParseSectionText = function(_content,_out){\n        if (!_content) return;\n        var _lines = _content.split('\\n');\n        if (!_lines||!_lines.length) return;\n        for(var i=0,l=_lines.length,_line;i<l;i++){\n            _line = _lines[i];\n            if (!!_trim){\n                _line = _line.trim();\n                if (!_line) continue;\n            } \n            _doParseSectionTextLine(_line,_out);\n            if (!!_trim&&i<l-1) _out.push('__OUT.push(\\'\\\\n\\');');\n        }\n    };\n    /*\n     * 解析内容，内容中可能包含${a}或者${%a%}取值语句\n     * @param  {String} 待解析语句\n     * @param  {Array}  内容输出\n     * @return {Void}\n     */\n    var _doParseSectionTextLine = (function(){\n        var _raor = /\\|\\|/g,\n            _rvor = /#@@#/g;\n        return function(_content,_out){\n            // defined used variable\n            var _prvmrkend = '}',_prvexpend = -1,\n                _length = _content.length,\n                _begin,_end,_begexp,_endexp,_exparr;\n            while((_prvexpend+_prvmrkend.length)<_length){\n                _begin = '${'; _end = '}';\n                _begexp = _content.indexOf(_begin,_prvexpend+_prvmrkend.length);\n                if (_begexp<0) break;\n                // parse ${% customer.firstName %} syntax\n                if (_content.charAt(_begexp+2)=='%'){\n                    _begin = '${%'; _end = '%}';\n                }\n                _endexp = _content.indexOf(_end,_begexp+_begin.length);\n                if (_endexp<0) break;\n                _doParseText(_content.substring(_prvexpend+_prvmrkend.length,_begexp),_out);\n                // parse expression: 'firstName|default:\"John Doe\"|capitalize'.split('|')\n                _exparr = _content.substring(_begexp+_begin.length,_endexp).replace(_raor,'#@@#').split('|');\n                for(var i=0,l=_exparr.length;i<l;_exparr[i]=_exparr[i].replace(_rvor,'||'),i++);\n                _out.push('__OUT.push('); _doParseExpression(_exparr,_out); _out.push(');');\n                _prvmrkend = _end; _prvexpend = _endexp;\n            }\n            _doParseText(_content.substring(_prvexpend+_prvmrkend.length),_out);\n        };\n    })();\n    /*\n     * 解析纯文本内容，不包含需要解析的内容\n     * @param  {String} 待解析内容\n     * @param  {Array}  内容输出\n     * @return {Void}\n     */\n    var _doParseText = (function(){\n        var _map = {r:/\\n|\\\\|\\'/g,'\\n':'\\\\n','\\\\':'\\\\\\\\','\\'':'\\\\\\''};\n        var _doEncode = function(_content){\n            return (_content||'').replace(_map.r,function($1){\n                return _map[$1]||$1;\n            });\n        };\n        return function(_content,_out){\n            if (!_content) return;\n            _out.push('__OUT.push(\\''+_doEncode(_content)+'\\');');\n        };\n    })();\n    /*\n     * 解析模板为执行函数\n     * @param  {String}   模板内容\n     * @return {Function} 模板执行函数\n     */\n    var _doParseTemplate = (function(){\n        var _rtab = /\\t/g,\n            _rnln = /\\n/g,\n            _rlne = /\\r\\n?/g;\n        var _doSearchEnd = function(_content,_begin){\n            var _index = _content.indexOf(\"}\",_begin+1);\n            // for {for x in \\{a:'aaa',b:'bbbb'\\}}\n            while(_content.charAt(_index-1)=='\\\\'){\n                _index = _content.indexOf(\"}\",_index+1);\n            }\n            return _index;\n        };\n        var _doParseVarMap = function(){\n            var _arr = [],\n                _arg = arguments[0];\n            for(var x in _arg){\n                x = (x||'').trim();\n                if (!x) continue;\n                _arr.push(x+'=$v(\\''+x+'\\')');\n            }\n            return _arr.length>0?('var '+_arr.join(',')+';'):'';\n        };\n        return function(_content){\n            _vars = {};\n            _content = _content.replace(_rlne,'\\n').replace(_rtab,'    ');\n            var _ftxt = ['if(!__CTX) return \\'\\';',''];\n            _ftxt.push('function $v(__NAME){var v = __CTX[__NAME];return v==null?window[__NAME]:v;};');\n            _ftxt.push('var defined=function(__NAME){return __CTX[__NAME]!=null;},');\n            _ftxt.push('__OUT=[];');\n            // defiend used variables\n            var _prvend = -1,_length = _content.length;\n            var _stmtbeg,_stmtend,_statement,\n                _blockrx,_blktmp,_blkend,_blkmrk,_blktxt;\n            // search content\n            while((_prvend+1)<_length){\n                // search statement begin\n                _stmtbeg = _prvend;\n                _stmtbeg = _content.indexOf(\"{\",_stmtbeg+1);\n                while(_stmtbeg>=0){\n                    _stmtend = _doSearchEnd(_content,_stmtbeg);\n                    _statement = _content.substring(_stmtbeg,_stmtend);\n                    _blockrx = _statement.match(_config.blk);\n                    // minify/eval/cdata implementation\n                    if (!!_blockrx){\n                        _blktmp = _blockrx[1].length+1;\n                        _blkend = _content.indexOf('}',_stmtbeg+_blktmp);\n                        if (_blkend>=0){\n                            // gen block end marker\n                            _blkmrk = _blkend-_stmtbeg-_blktmp<=0\n                                    ? ('{/'+_blockrx[1]+'}')\n                                    : _statement.substr(_blktmp+1);\n                            _blktmp = _content.indexOf(_blkmrk,_blkend+1);\n                            // parse block content\n                            if (_blktmp>=0){\n                                _doParseSectionText(_content.substring(_prvend+1,_stmtbeg),_ftxt);\n                                // get block text and parse\n                                _blktxt = _content.substring(_blkend+1,_blktmp);\n                                switch(_blockrx[1]){\n                                    case 'cdata' : _doParseText(_blktxt,_ftxt); break;\n                                    case 'minify': _doParseText(_blktxt.replace(_rnln,' ').replace(_rspc,' '),_ftxt); break;\n                                    case 'eval'  : if (!!_blktxt) _ftxt.push('__OUT.push((function(){'+_blktxt+'})());'); break;\n                                }\n                                _stmtbeg = _prvend = _blktmp+_blkmrk.length-1;\n                            }\n                        }\n                    }else if(_content.charAt(_stmtbeg-1)!='$'&&\n                             _content.charAt(_stmtbeg-1)!='\\\\'&&\n                             _statement.substr(_statement.charAt(1)=='/'?2:1)\n                                                         .search(_config.tag)==0){\n                        // break when result is a statement\n                        break;\n                    }\n                    _stmtbeg = _content.indexOf(\"{\",_stmtbeg+1);\n                }\n                if (_stmtbeg<0) break;\n                _stmtend = _doSearchEnd(_content,_stmtbeg);\n                if (_stmtend<0) break;\n                // parse content\n                _doParseSectionText(_content.substring(_prvend+1,_stmtbeg),_ftxt);\n                _doParseStatement(_content.substring(_stmtbeg,_stmtend+1),_ftxt);\n                _prvend = _stmtend;\n            }\n            _doParseSectionText(_content.substring(_prvend+1),_ftxt);\n            _ftxt.push(';return __OUT.join(\"\");'); \n            _ftxt[1] = _doParseVarMap(_vars);\n            _vars = null;\n            //console.log(_ftxt.join(''));\n            return new Function('__CTX','__MDF',_ftxt.join(''));\n        };\n    })();\n    // interface\n    /**\n     * 取模板随机数种子\n     *\n     * 代码举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/template/trimpath.nej'\n     * ],function(){\n     *     // 模版统一随机标识\n     *     var _seed = TrimPath.seed();\n     * });\n     * ```\n     * \n     * @method TrimPath.seed\n     * @return {String} 随机数种子\n     */\n    TrimPath.seed = function(){\n        return _seed;\n    };\n    /**\n     * 根据模板的序列号合并模板数据\n     * \n     * 代码举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/template/trimpath'\n     * ],function(){\n     *     // 模版合并数据\n     *     var _html = TrimPath.merge(\n     *         _jst_id,{\n     *             a:'aaaaaa',\n     *             b:'bbbbbbbbbb',\n     *             c:'cccccccccccc'\n     *         }\n     *     );\n     * });\n     * ```\n     *\n     * @method TrimPath.merge\n     * @param  {String} arg0 - 模板序列号\n     * @param  {Object} arg1 - 模板数据\n     * @param  {Object} arg2 - 扩展接口\n     * @return {String}        合并数据后的内容\n     */\n    TrimPath.merge = (function(){\n        var _fcache = {};\n        // for test\n        TrimPath.dump = function(){\n            return {\n                func:_fcache,\n                text:_tcache\n            };\n        };\n        return function(_sn,_data,_extend){\n            try{\n                _data = _data||{};\n                if (!_fcache[_sn]&&!_tcache[_sn])\n                    return '';\n                if (!_fcache[_sn]){\n                    _fcache[_sn] = _doParseTemplate(_tcache[_sn]);\n                    delete _tcache[_sn];\n                }\n                if (!!_extend){\n                    for(var x in _config.ext)\n                        if (!_extend[x])\n                            _extend[x] = _config.ext[x];\n                }\n                return _fcache[_sn](_data,_extend||_config.ext);\n            }catch(ex){\n                return ex.message||'';\n            }\n        };\n    })();\n    /**\n     * 添加JST模板，JST模板可以是节点的值\n     *\n     * 代码举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/template/trimpath'\n     * ],function(){\n     *     // 解析缓存模版\n     *     var _jst_id = TrimPath.merge(\n     *         '<div>\\\n     *              <p>${a}</p>\\\n     *              <p>${b}</p>\\\n     *              <p>${c}</p>\\\n     *          </div>'\n     *     );\n     * });\n     * ```\n     *\n     * @method TrimPath.parse\n     * @param  {String}  arg0 - JST模板内容\n     * @param  {Boolean} arg1 - 是否保留节点\n     * @return {String}         JST模板在缓存中的标识\n     */\n    TrimPath.parse = (function(){\n        var _xeed = +new Date;\n        return function(_content,_sn){\n            if (!_content) return '';\n            _sn = _sn||('ck-'+(_xeed++));\n            if (_tcache[_sn]!=null){\n                console.warn('jst template overwrited with key '+_sn);\n                console.debug('old template content: '+_tcache[_sn].replace(/\\n/g,' '));\n                console.debug('new template content: '+_content.replace(/\\n/g,' '));\n            }\n            _tcache[_sn] = _content;\n            return _sn;\n        };\n    })();\n})();"
  },
  {
    "path": "src/util/timer/animation.js",
    "content": "/*\n * ------------------------------------------\n * 动画时钟实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/timer/animation */\nNEJ.define([\n    'base/platform',\n    '{platform}animation.js'\n],function(_m,_h,_p,_o,_f,_r){\n    /**\n     * 请求动画\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/timer/animation'\n     * ],function(_p){\n     *     // 桌面端一秒钟调用12.5次，ios端没秒调用20次，否则调用33次\n     *     var _id  = _p.requestAnimationFrame(\n     *         function(_time){\n     *             console.log(_time);\n     *         }\n     *     );\n     * });\n     * ```\n     * \n     * @method module:util/timer/animation.requestAnimationFrame\n     * @param  {Function} arg0 - 动画回调\n     * @return {String}          动画标识\n     */\n    _p.requestAnimationFrame = function(){\n        return _h.__requestAnimationFrame.apply(null,arguments);\n    };\n    /**\n     * 取消动画\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/timer/animation'\n     * ],function(_p){\n     *     var _id  = _p.requestAnimationFrame(\n     *         function(_time){\n     *             console.log(_time);\n     *         }\n     *     );\n     *     // 停止掉时钟\n     *     _p.cancelAnimationFrame(_id);\n     * });\n     * ```\n     * \n     * @method module:util/timer/animation.cancelAnimationFrame\n     * @param  {String} arg0 - 动画标识\n     * @return {Void}\n     */\n    _p.cancelAnimationFrame = function(){\n        _h.__cancelAnimationFrame.apply(null,arguments);\n    };\n    \n    if (CMPT){\n        if (!this.requestAnimationFrame){\n            this.requestAnimationFrame = _p.requestAnimationFrame;\n        }\n        if (!this.cancelAnimationFrame){\n            this.cancelAnimationFrame = _p.cancelAnimationFrame;\n        }\n    }\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/timer/demo/a.js",
    "content": "NEJ.define([\n    'util/timer/animation'\n],function(p){\n    var abc = function () {\n        log(+new Date);\n        p.requestAnimationFrame(abc);\n    };\n    p.requestAnimationFrame(abc);\n});"
  },
  {
    "path": "src/util/timer/demo/output.js",
    "content": "if(\"undefined\"==typeof I$)I$=function(){var e={},n=function(){return!1},i={};var r=function(n,i){return e.toString.call(n)===\"[object \"+i+\"]\"};return function(e,t){var o=i[e],a=r(t,\"Function\");if(null!=t&&!a)o=t;if(a){var s=[];for(var u=2,c=arguments.length;u<c;u++)s.push(arguments.callee(arguments[u]));var l={};s.push.call(s,l,{},n,[]);var f=t.apply(null,s)||l;if(!o||!r(f,\"Object\"))o=f;else if(Object.keys)for(var p=Object.keys(f),u=0,c=p.length,m;u<c;u++){m=p[u];o[m]=f[m]}else for(var m in f)o[m]=f[m]}if(null==o)o={};i[e]=o;return o}}();I$(6,function(e,n,i,r){var t=Function.prototype;t._$aop=function(e,n){var n=n||i,e=e||i,t=this;return function(){var i={args:r.slice.call(arguments,0)};e(i);if(!i.stopped){i.value=t.apply(this,i.args);n(i)}return i.value}};t._$bind=function(){var e=arguments,n=arguments[0],i=this;return function(){var t=r.slice.call(e,1);r.push.apply(t,arguments);return i.apply(n||null,t)}};t._$bind2=function(){var e=arguments,n=r.shift.call(e),i=this;return function(){r.push.apply(arguments,e);return i.apply(n||null,arguments)}};var t=String.prototype;if(!t.trim)t.trim=function(){var e=/(?:^\\s+)|(?:\\s+$)/g;return function(){return this.replace(e,\"\")}}();if(!this.console)this.console={log:i,error:i};if(!0){NEJ=this.NEJ||{};NEJ.copy=function(e,i){e=e||{};i=i||n;for(var r in i)if(i.hasOwnProperty(r))e[r]=i[r];return e};NEJ=NEJ.copy(NEJ,{O:n,R:r,F:i,P:function(e){if(!e||!e.length)return null;var n=window;for(var i=e.split(\".\"),r=i.length,t=\"window\"==i[0]?1:0;t<r;n=n[i[t]]=n[i[t]]||{},t++);return n}});return NEJ}return e});I$(3,function(e,n,i,r,t){var o=this.navigator.platform,a=this.navigator.userAgent;var s={mac:o,win:o,linux:o,ipad:a,ipod:a,iphone:o,android:a};n._$IS=s;for(var u in s)s[u]=new RegExp(u,\"i\").test(s[u]);s.ios=s.ipad||s.iphone||s.ipod;s.tablet=s.ipad;s.desktop=s.mac||s.win||s.linux&&!s.android;n._$is=function(e){return!!s[e]};var c={engine:\"unknow\",release:\"unknow\",browser:\"unknow\",version:\"unknow\",prefix:{css:\"\",pro:\"\",clz:\"\"}};n._$KERNEL=c;if(/msie\\s+(.*?);/i.test(a)||/trident\\/.+rv:([\\d\\.]+)/i.test(a)){c.engine=\"trident\";c.browser=\"ie\";c.version=RegExp.$1;c.prefix={css:\"ms\",pro:\"ms\",clz:\"MS\",evt:\"MS\"};var l={6:\"2.0\",7:\"3.0\",8:\"4.0\",9:\"5.0\",10:\"6.0\",11:\"7.0\"};c.release=l[document.documentMode]||l[parseInt(c.version)]}else if(/webkit\\/?([\\d.]+?)(?=\\s|$)/i.test(a)){c.engine=\"webkit\";c.release=RegExp.$1||\"\";c.prefix={css:\"webkit\",pro:\"webkit\",clz:\"WebKit\"}}else if(/rv\\:(.*?)\\)\\s+gecko\\//i.test(a)){c.engine=\"gecko\";c.release=RegExp.$1||\"\";c.browser=\"firefox\";c.prefix={css:\"Moz\",pro:\"moz\",clz:\"Moz\"};if(/firefox\\/(.*?)(?=\\s|$)/i.test(a))c.version=RegExp.$1||\"\"}else if(/presto\\/(.*?)\\s/i.test(a)){c.engine=\"presto\";c.release=RegExp.$1||\"\";c.browser=\"opera\";c.prefix={css:\"O\",pro:\"o\",clz:\"O\"};if(/version\\/(.*?)(?=\\s|$)/i.test(a))c.version=RegExp.$1||\"\"}if(\"unknow\"==c.browser){var l=[\"chrome\",\"maxthon\",\"safari\"];for(var f=0,p=l.length,m;f<p;f++){if(\"safari\"==l[f])m=\"version\";else if(\"chrome\"==l[f])m=\"[chrome|CriOS]\";else m=l[f];if(new RegExp(m+\"/(.*?)(?=\\\\s|$)\",\"i\").test(a)){c.browser=l[f];c.version=RegExp.$1.trim();break}}}n._$SUPPORT={};n._$support=function(e){return!!n._$SUPPORT[e]};if(!0)e.copy(e.P(\"nej.p\"),n);return n},6);I$(5,function(e,n,i,r,t){var o=this,a=e._$KERNEL.prefix.pro,s=e._$is(\"desktop\")?80:e._$is(\"ios\")?50:30;n.__requestAnimationFrame=function(){var n=e._$is(\"android\")?null:o.requestAnimationFrame||o[a+\"RequestAnimationFrame\"];return function(){if(!n)n=function(e){return window.setTimeout(function(){try{e(+new Date)}catch(n){}},1e3/s)};return n.apply(this,arguments)}}();n.__cancelAnimationFrame=function(){var n=e._$is(\"android\")?null:o.cancelAnimationFrame||o[a+\"CancelAnimationFrame\"];return function(){if(!n)n=function(e){window.clearTimeout(e)};return n.apply(this,arguments)}}();return n},3);I$(4,function(e,n){return e},5,3);I$(1,function(e,n,i,r,t,o){i.requestAnimationFrame=function(){n.__requestAnimationFrame.apply(null,arguments)};i.cancelAnimationFrame=function(){n.__cancelAnimationFrame.apply(null,arguments)};if(!0){if(!this.requestAnimationFrame)this.requestAnimationFrame=i.requestAnimationFrame;if(!this.cancelAnimationFrame)this.cancelAnimationFrame=i.cancelAnimationFrame}return i},3,4);I$(2,function(e){var n=function(){log(+new Date);e.requestAnimationFrame(n)};e.requestAnimationFrame(n)},1);"
  },
  {
    "path": "src/util/timer/demo/test.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <title>klass demo</title>\n    <meta charset=\"utf-8\" />\n    <script>\n        function log(m){\n            var p = document.createElement('p');\n            p.innerHTML = m;\n            document.body.appendChild(p);\n        }\n    </script>\n</head>\n<body>\n<script src=\"../../../define.js\"></script>\n<script>\n    NEJ.define([\n        'util/timer/animation'\n    ],function(p){\n        var abc = function () {\n            log(+new Date);\n            p.requestAnimationFrame(abc);\n        };\n        p.requestAnimationFrame(abc);\n    });\n</script>\n</body>\n</html>"
  },
  {
    "path": "src/util/timer/demo/test.min.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <title>animation demo</title>\n    <meta charset=\"utf-8\" />\n    <script>\n        function log(m){\n            var p = document.createElement('p');\n            p.innerHTML = m;\n            document.body.appendChild(p);\n        }\n    </script>\n</head>\n<body>\n<script src=\"output.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "src/util/timer/interval.js",
    "content": "/*\n * ------------------------------------------\n * 统一处理间隔时钟实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/timer/interval */\nNEJ.define([\n    'base/global',\n    'base/util'\n],function(NEJ,_u,_p,_o,_f,_r){\n    var _tcache = {}; // interval:{tm:timer,fn:[{id:23,cb:function} ...]}\n                      // timer_id:interval\n    /**\n     * 请求定时器操作\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/timer/interval'\n     * ],function(_p){\n     *     // 设置一个定时器，一秒一次\n     *     var _id1 = _p.requestInterval(\n     *         function(_options){\n     *             // TODO\n     *         },1000\n     *     );\n     *     \n     *     // 设置一个定时器，一秒一次\n     *     var _id2 = _p.requestInterval(\n     *         function(_options){\n     *             // TODO\n     *         },1000\n     *     );\n     *     \n     *     // 时间间隔相同的回调，按照里面的列表进行一次循环。\n     *     // 回调顺序是id1的回调，id2的回调\n     * });\n     * ```\n     * \n     * @method module:util/timer/interval.requestInterval\n     * @param  {Function} arg0 - 回调函数\n     * @param  {Number}   arg1 - 时钟间隔\n     * @return {String}          时钟ID\n     */\n    _p.requestInterval = (function(){\n        var _doCallback = function(_item){\n            try{_item.cb(+new Date);}catch(ex){}\n        };\n        var _doTimerTrigger = function(_interval){\n            var _cache = _tcache[_interval];\n            if (!_cache) return;\n            _u._$forEach(_cache.fn,_doCallback);\n        };\n        return function(_callback,_interval){\n            if (!_u._$isFunction(_callback)){\n                return null;\n            }\n            var _cache = _tcache[_interval];\n            if (!_cache){\n                _cache = {fn:[]};\n                _tcache[_interval] = _cache;\n            }\n            var _id = _u._$uniqueID();\n            _tcache[_id] = _interval;\n            _cache.fn.push({id:_id,cb:_callback});\n            if (_cache.tm==null){\n                _cache.tm = window.setInterval(\n                    _doTimerTrigger._$bind(\n                        null,_interval\n                    ),_interval\n                );\n            }\n            return _id;\n        };\n    })();\n    /**\n     * 取消时钟操作\n     * \n     * 脚本举例\n     * ```javascript\n     * NEJ.define([\n     *     'util/timer/interval'\n     * ],function(_p){\n     *     // 取消掉id1的定时器，保留一秒一次的id2的回调\n     *     // 如果同一个时间间隔的，id2也被取消，整个回调被取消\n     *     _p.cancelInterval(_id1);\n     * });\n     * ```\n     * \n     * @method module:util/timer/interval.cancelInterval\n     * @param  {String} arg0 - 时钟ID\n     * @return {Void}\n     */\n    _p.cancelInterval = function(_tid){\n        var _interval = _tcache[_tid],\n            _cache = _tcache[_interval];\n        if (!_cache) return;\n        var _list = _cache.fn;\n        _u._$reverseEach(\n            _list,function(_item,_index,_list){\n                if (_item.id==_tid){\n                    _list.splice(_index,1);\n                    return !0;\n                }\n            }\n        );\n        if (!_list.length){\n            window.clearInterval(_cache.tm);\n            delete _tcache[_tid];\n            delete _tcache[_interval];\n        }\n    };\n    \n    if (CMPT){\n        NEJ.copy(this,_p);\n    }\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/timer/platform/animation.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    'base/platform'\n],function(_m,_p,_o,_f,_r){\n    var _this = this,\n        _prefix = _m._$KERNEL.prefix.pro,\n        _fps = _m._$is('desktop')?80:(_m._$is('ios')?50:30);\n    /**\n     * 请求动画\n     * @param  {Function} 动画回调\n     * @return {String}   动画标识\n     */\n    _p.__requestAnimationFrame = (function(){\n        var _handler = _m._$is('android')?null:(\n            _this.requestAnimationFrame||\n            _this[_prefix+'RequestAnimationFrame']\n        );\n        return function(){\n            if (!_handler){\n                _handler = function(_callback){\n                    return window.setTimeout(\n                        function(){\n                            try{_callback(+new Date);}catch(ex){}\n                        },1000/_fps\n                    );\n                };\n            }\n            return _handler.apply(this,arguments);\n        };\n    })();\n    /**\n     * 取消动画\n     * @param  {String} 动画标识\n     * @return {Void}\n     */\n    _p.__cancelAnimationFrame = (function(){\n        var _handler = _m._$is('android')?null:(\n            _this.cancelAnimationFrame||\n            _this[_prefix+'CancelAnimationFrame']\n        );\n        return function(){\n            if (!_handler){\n                _handler = function(_id){\n                    window.clearTimeout(_id);\n                };\n            }\n            return _handler.apply(this,arguments);\n        };\n    })();\n    \n    return _p;\n});\n"
  },
  {
    "path": "src/util/timer/platform/animation.patch.js",
    "content": "/*\n * ------------------------------------------\n * 平台适配接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\nNEJ.define([\n    './animation.js',\n    'base/platform'\n],function(_h,_m){\n    return _h;\n});\n"
  },
  {
    "path": "src/util/toggle/demo/toggle.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>NEJ实例 - Toggle</title>\n    <meta charset=\"utf-8\" />\n    \n    <style>\n        .abc{background:#fdc;}\n        .js-toggle{background:#0000FF;}\n    </style>\n    \n  </head>\n  <body>\n    \n    <div class=\"abc\" id=\"abc\">123456</div>\n    \n    <script src=\"../../../define.js\"></script>\n    <script>\n        NEJ.define([\n            'util/toggle/toggle'\n        ],function(_t){\n            _t._$toggle(\n                'abc',{\n                    element:'abc'\n                }\n            );\n        });\n    </script>\n  </body>\n</html>"
  },
  {
    "path": "src/util/toggle/test/toggle.test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>toggle测试页</title>\n        <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-1.14.0.css\" type=\"text/css\" media=\"screen\" />\n        <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-1.14.0.js\"></script>\n    </head>\n    <body>\n        <h1 id=\"qunit-header\">Qunit xdr test</h1>\n        <h2 id=\"qunit-banner\"></h2>\n        <div id=\"qunit-testrunner-toolbar\"></div>\n        <h2 id=\"qunit-userAgent\"></h2>\n        <ol id=\"qunit-tests\"></ol>\n        <div id=\"qunit-fixture\"></div>\n        <div class=\"bar\" id=\"click-bar\">可点击区域</div>\n            <div class=\"shw\" id=\"toggle-node\">\n                <p>content content</p>\n                <p>content content</p>\n                <p>content content</p>\n                <p>content content</p>\n            </div>\n        </div>\n        <script src=\"../../../define.js?pro=./\"></script>\n        <script type=\"text/javascript\" src=\"./toggle.test.js\"></script>\n    </body>\n</html>"
  },
  {
    "path": "src/util/toggle/test/toggle.test.js",
    "content": "NEJ.define(['util/toggle/toggle'],function(){\n    var _  = NEJ.P,\n        _e = _('nej.e'),\n        _v = _('nej.v');\n    test('toggle',function(){\n        _e._$toggle('click-bar',{element:'toggle-node',clazz:'cxx'});\n        _v._$dispatchEvent('click-bar','click');\n        equal(_e._$get('toggle-node').className.indexOf('cxx') >= 0,true,'toggle')\n\n        // // 同时自定义切换样式和节点\n        // _e._$toggle('click-bar',{\n        //     clazz:'js-show',\n        //     element:'toggle-node',\n        //     ontoggle:function(_event){\n        //         // _event.clazz   切换的样式名称\n        //         // _event.target  触发切换事件的节点\n        //         // _event.toggled 是否增加了切换样式\n        //         debugger;\n        //         // TODO\n        //     }\n        // });\n    });\n});"
  },
  {
    "path": "src/util/toggle/toggle.js",
    "content": "/*\n * ------------------------------------------\n * TOGGLE接口实现文件\n * @version  1.0\n * @author   genify(caijf@corp.netease.com)\n * ------------------------------------------\n */\n/** @module util/toggle/toggle */\nNEJ.define([\n    'base/global',\n    'base/element',\n    'base/util',\n    'base/event',\n    'base/chain'\n],function(NEJ,_e,_u,_v,_x,_p,_o,_f,_r){\n    /**\n     * 点击切换样式，可以控制两种效果的交替显示\n     *\n     * 样式举例\n     * ```css\n     *   .box .shw{display:none;}\n     *   .box.js-toggle .shw{display:block;}\n     * ```\n     *\n     * 结构举例\n     * ```html\n     *   <div class=\"box\">\n     *     <div class=\"bar\" id=\"click-bar\">可点击区域</div>\n     *     <div class=\"shw\">\n     *       <p>content content</p>\n     *       <p>content content</p>\n     *       <p>content content</p>\n     *       <p>content content</p>\n     *     </div>\n     *   </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'util/toggle/toggle'\n     *   ],function(_e){\n     *       // 点击click-bar，交替显示shw节点\n     *       _e._$toggle('click-bar');\n     *\n     *       // 自定义切换样式\n     *       _e._$toggle('click-bar','js-show');\n     *   });\n     * ```\n     *\n     * 样式举例\n     * ```css\n     *   .box{display:none;}\n     *   .box.js-toggle{display:block;}\n     * ```\n     *\n     * 结构举例\n     * ```html\n     *   <div class=\"box\">\n     *     <div class=\"bar\" id=\"click-bar\">可点击区域</div>\n     *     <div class=\"shw\" id=\"toggle-node\">\n     *       <p>content content</p>\n     *       <p>content content</p>\n     *       <p>content content</p>\n     *       <p>content content</p>\n     *     </div>\n     *   </div>\n     * ```\n     *\n     * 脚本举例\n     * ```javascript\n     *   NEJ.define([\n     *       'util/toggle/toggle'\n     *   ],function(_e){\n     *       // 自定义切换样式\n     *       _e._$toggle('click-bar','toggle-node');\n     *\n     *       // 同时自定义切换样式和节点\n     *       _e._$toggle('click-bar',{\n     *           clazz:'js-show',\n     *           element:'toggle-node',\n     *           ontoggle:function(_event){\n     *               // _event.clazz   切换的样式名称\n     *               // _event.target  触发切换事件的节点\n     *               // _event.toggled 是否增加了切换样式\n     *\n     *               // TODO\n     *           },\n     *           onbeforetoggle:function(_event){\n     *               // _event.clazz   切换的样式名称\n     *               // _event.target  触发切换事件的节点\n     *               // _event.stopped 是否阻止切换操作\n     *\n     *               // TODO\n     *           }\n     *       });\n     *   });\n     * ```\n     *\n     * @method   module:util/toggle/toggle._$toggle\n     * @param    {String|Node}   arg0     - 触发切换节点\n     * @param    {String|Object} arg1     - 切换配置信息，输入字符串表示样式或者节点\n     * @property {String}        clazz    - 样式名称，默认为js-toggle\n     * @property {String|Node}   element  - 切换样式的节点，默认为父节点\n     * @property {Function}      ontoggle - 节点样式切换触发事件，输入信息{clazz,target,toggled}\n     * @property {Function}      onbeforetoggle - 节点样式切换之前触发事件，输入信息{clazz,target,stopped}\n     * @return   {Void}\n     */\n    /**\n     * @method CHAINABLE._$toggle\n     * @see module:util/toggle/toggle._$toggle\n     */\n    _p._$toggle = (function(){\n        // click event\n        var _doClick = function(_options,_ev){\n            var _element = _e._$get(_options.element),\n                _clazz = _options.clazz,\n                _event = {\n                    event:_ev,\n                    clazz:_clazz,\n                    target:_element,\n                    source:_e._$get(_options.source)\n                };\n            _options.onbeforetoggle.call(null,_event);\n            if (!!_event.stopped) return;\n            // toggle element\n            if (_e._$hasClassName(_element,_clazz)){\n                _event.toggled = !1;\n                _e._$delClassName(_element,_clazz);\n            }else{\n                _event.toggled = !0;\n                _e._$addClassName(_element,_clazz);\n            }\n            _options.ontoggle.call(null,_event);\n        };\n        return function(_element,_options){\n            _element = _e._$get(_element);\n            if (!!_element){\n                var _obj = {\n                    ontoggle:_f,\n                    onbeforetoggle:_f,\n                    clazz:'js-toggle',\n                    source:_e._$id(_element),\n                    element:_element.parentNode\n                };\n                if (_u._$isString(_options)){\n                    var _node = _e._$get(_options);\n                    !!_node ? _obj.element = _node\n                            : _obj.clazz = _options;\n                }else{\n                    _u._$fetch(_obj,_options);\n                    _obj.element = _e._$get(_obj.element);\n                }\n                _obj.element = _e._$id(_obj.element);\n                _v._$addEvent(\n                    _element,'click',\n                    _doClick._$bind(null,_obj)\n                );\n            }\n        };\n    })();\n    // for chainable method\n    _x._$merge(_p);\n\n    if (CMPT){\n        NEJ.copy(NEJ.P('nej.e'),_p);\n    }\n\n    return _p;\n});\n"
  }
]